home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Core / Prefs.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  84.5 KB  |  2,898 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Prefs.cpp
  3.  
  4.     Contains:    Implementation for Preferences class.
  5.  
  6.     Owned by:    Ed Lai
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <17>     7/26/96    RA        1372498: We should register a folder
  13.                                     containing an shlb w/ CFM even if it
  14.                                     contains no nmaps
  15.         <16>     7/25/96    DH        Fixed Read_nmap_buffer so that it now
  16.                                     Reraises if there is an exception, instead
  17.                                     of eating it and causing an infinite loop.
  18.         <15>     6/27/96    EL        1363389: while resolving aliases, alias not
  19.                                     found => not on current volume => can be
  20.                                     removed.
  21.         <14>     6/27/96    TJ        When scanning folders check for special
  22.                                     editors type, and only register folders
  23.                                     that have CFM type.
  24.         <13>     6/25/96    EL        1210509: defer to a later version. 1362088:
  25.                                     Do not alert when in background.
  26.         <12>     6/24/96    RA        1358594: Binding crashes if OpenDoc prefs
  27.                                     file is locked, don't write if prefs is
  28.                                     locked.
  29.         <11>     6/22/96    EL        1210509: alert when two editors with same
  30.                                     nmap. 1218948: alert when deleting pref
  31.                                     file. 1356059: preserve size resource when
  32.                                     pref file deleted.
  33.         <10>      6/4/96    EL        1283131: Separate Alerts for bad alias in
  34.                                     editor folder and in library folder.
  35.          <9>     5/31/96    jpa        T10012: Added editor namespace
  36.                                     EditorPlatformSignature.
  37.          <8>     5/24/96    jpa        1213332: Force 68k alignment of persistent
  38.                                     structs.
  39.          <7>     5/23/96    RA        1330687: BndNSUtl should use
  40.                                     platformFile->read instead of FSRead
  41.          <6>     5/22/96    EL        #1263100: Allow dragging of dialog, pass
  42.                                     update event to other windows, visual
  43.                                     feedback in dialog after cancel.
  44.          <5>     5/17/96    EL        #1263100: When building nmap cache file,
  45.                                     show dialog with progress bar so it can be
  46.                                     canceled, and do not mount server while
  47.                                     resolving alias.
  48.          <4>      5/3/96    EL        1257565: Optimized speed of
  49.                                     LoadCacheRezData(from Jens). Use assignment
  50.                                     instead of ODBlockMove for short and long.
  51.                                     1333188 Do not use Hard-coded constant.
  52.          <3>      2/2/96    TJ        We only delete the prefrences if they are
  53.                                     older then the oldest version we can read.
  54.          <2>      1/5/96    JP        1308887: Fixed computation of language code
  55.                                     in GetAETEs
  56.          
  57.     To Do:
  58.         
  59.     In Progress:
  60.         
  61. */
  62.  
  63. #ifndef _EXCEPT_
  64. #include "Except.h"
  65. #endif
  66.  
  67. #ifndef _PREFS_
  68. #include "Prefs.h"
  69. #endif
  70.  
  71. #ifndef _PREFSDEF_
  72. #include "PrefsDef.h"
  73. #endif
  74.  
  75. // this is here only because error codes like kODErrCannotFindOpenDocLibrariesFolder,
  76. // which should be elsewhere, are needed.
  77. #ifndef _SHELLDEF_
  78. #include <ShellDef.h>
  79. #endif
  80.  
  81. #ifndef _PLFMFILE_
  82. #include "PlfmFile.h"
  83. #endif
  84.  
  85. #ifndef SOM_ODNameSpaceManager_xh
  86. #include "NmSpcMg.xh"
  87. #endif
  88.  
  89. #ifndef SOM_ODNameSpace_xh
  90. #include "NamSpac.xh"
  91. #endif
  92.  
  93. #ifndef SOM_ODObjectNameSpace_xh
  94. #include "ObjectNS.xh"
  95. #endif
  96.  
  97. #ifndef SOM_ODValueNameSpace_xh
  98. #include "ValueNS.xh"
  99. #endif
  100.  
  101. #ifndef SOM_ODDispatcher_xh
  102. #include <Disptch.xh>
  103. #endif
  104.  
  105. #ifndef _ODSESSN_
  106. #include "ODSessn.xh"
  107. #endif
  108.  
  109. #ifndef SOM_ODTypeList_xh
  110. #include "TypeList.xh"
  111. #endif
  112.  
  113. #ifndef SOM_ODTranslation_xh
  114. #include <Translt.xh>
  115. #endif
  116.  
  117. #ifndef __SCRIPT__
  118. #include <Script.h>
  119. #endif
  120.  
  121. #ifndef _USERSRCM_
  122. #include "UseRsrcM.h"
  123. #endif
  124.  
  125. #ifndef __ERRORS__
  126. #include <Errors.h>
  127. #endif
  128.  
  129. #ifndef _STDDEFS_
  130. #include "StdDefs.xh"
  131. #endif
  132.  
  133. #ifndef _ITEXT_
  134. #include "IText.h"
  135. #endif
  136.  
  137. #ifndef _LINKLIST_
  138. #include "LinkList.h"
  139. #endif
  140.  
  141. #ifndef _PASCLSTR_
  142. #include "PasclStr.h"
  143. #endif
  144.  
  145. #ifndef _BNDNSUTL_
  146. #include "BndNSUtl.h"
  147. #endif
  148.  
  149. #ifndef _ISOSTR_
  150. #include "ISOStr.h"
  151. #endif
  152.  
  153. #ifndef _ODUTILS_
  154. #include <ODUtils.h>
  155. #endif
  156.  
  157. #ifndef _DLOGUTIL_
  158. #include <DlogUtil.h>
  159. #endif
  160.  
  161. #ifndef __ALIASES__
  162. #include <Aliases.h>
  163. #endif
  164.  
  165. #ifndef _NMSPCUTL_
  166. #include <NmSpcUtl.h>
  167. #endif
  168.  
  169. #include <string.h>
  170.  
  171. #ifndef __RESOURCES__
  172. #include <Resources.h>
  173. #endif
  174.  
  175. #ifndef __FOLDERS__
  176. #include <Folders.h>
  177. #endif
  178.  
  179. #ifndef __FINDER__
  180. #include <Finder.h>        /* For kIsInvisible */
  181. #endif
  182.  
  183. #ifndef __CONTROLS__
  184. #include <Controls.h>    /* For kControlButtonPart */
  185. #endif
  186.  
  187. #ifndef __DIALOGS__
  188. #include <Dialogs.h>
  189. #endif
  190.  
  191. #ifndef _REGISTER_
  192. #include <RegisterFileLibs.h>
  193. #endif
  194.  
  195. #ifndef _MEMDEBG_
  196. #include <MemDebg.h>    /* Testing only */
  197. #endif
  198.  
  199. #ifndef SOM_ODStorageSystem_xh
  200. #include <ODStor.xh>
  201. #endif
  202.  
  203. #ifndef _TEMPOBJ_
  204. #include <TempObj.h>
  205. #endif
  206.  
  207. #ifndef __ASREGISTRY__
  208. #include <ASRegistry.h>
  209. #endif
  210.  
  211. #ifndef __CODEFRAGMENTS__
  212. #include <CodeFragments.h>
  213. #endif
  214.  
  215. #ifndef __DEVICES__
  216. #include <Devices.h>
  217. #endif
  218.  
  219. #pragma segment Preferences
  220.  
  221.  
  222. #undef LOGGING
  223. #define LOGGING 0
  224.  
  225. //==============================================================================
  226. // Constants
  227. //==============================================================================
  228.  
  229. const ODULong        kNumExpectedParts = 10;
  230.  
  231. const ODULong        kMinResynchTime = 2 * 60;    // Only check folders every 2 seconds
  232.  
  233.  
  234. /*    Following is the table of namespaces to be created by Prefs. The Editor Namespaces
  235.     are also cleared whenever we re-scan the Editors folders. */
  236.  
  237. struct NameSpaceSpec {
  238.     const char *name;
  239.     ODNSTypeSpec type;
  240. };
  241.  
  242. const kNPrefNameSpaces = 4;
  243.  
  244. #define kODFileFromEditor "FileFromEditor"
  245. static const NameSpaceSpec kPrefNameSpaces[kNPrefNameSpaces] = {
  246.         {kODSysPrefEditorKinds,        kODNSDataTypeODValue}
  247.         ,{kODSysPrefEditorCategories,kODNSDataTypeODValue}
  248.         ,{kODSysPrefContainerSuites,    kODNSDataTypeODValue}
  249.         ,{kODFileFromEditor,            kODNSDataTypeODValue}
  250.     };
  251.  
  252. const kNEditorNameSpaces = 10;
  253.  
  254. static const NameSpaceSpec kEditorNameSpaces[kNEditorNameSpaces] = {
  255.         {kODContainerSuite,            kODNSDataTypeODValue},    // From OD libraries (Bento)
  256.         {kODKind,                    kODNSDataTypeODObject},
  257.         {kODEditorKinds,            kODNSDataTypeODObject},
  258.         //{kODViewer,                    kODNSDataTypeODObject},
  259.         {kODViewer,                    kODNSDataTypeODValue},
  260.         //{kODEditorUserString,        kODNSDataTypeODObject},
  261.         //{kODKindUserString,            kODNSDataTypeODObject},
  262.         //{kODCategoryUserString,        kODNSDataTypeODObject},
  263.         {kODEditorUserString,        kODNSDataTypeODValue},
  264.         {kODKindUserString,            kODNSDataTypeODValue},
  265.         {kODCategoryUserString,        kODNSDataTypeODValue},
  266.         {kODKindOldMacOSType,        kODNSDataTypeODValue},
  267.         {kODEditorHelpFile,            kODNSDataTypeODValue},
  268.         {kODEditorPlatformSignature,kODNSDataTypeODValue}
  269.     };
  270.  
  271. const ODSShort kMaxDirDepth = 5;
  272.  
  273. #define typeAECache 'aech'
  274.  
  275. //==============================================================================
  276. // Scalar Types
  277. //==============================================================================
  278.  
  279. #if PRAGMA_ALIGN_SUPPORTED
  280. #pragma options align=mac68k
  281. #endif
  282.  
  283. struct cfragHeader {
  284.     ODULong    reserved1;
  285.     ODULong    reserved2;
  286.     ODULong    version;
  287.     ODULong    reserved3;
  288.     ODULong    reserved4;
  289.     ODULong    reserved5;
  290.     ODULong    reserved6;
  291.     ODULong    numFragDescs;
  292. };
  293.  
  294. typedef cfragHeader cfragHeader;
  295.  
  296. struct cfragDescHeader {
  297.     ODULong    arch;
  298.     ODULong    updateLevel;
  299.     ODULong    currVersion;
  300.     ODULong    oldDefVer;
  301.     ODULong    appStackSize;
  302.     ODSShort    appLibDir;
  303.     ODSByte    fragType;
  304.     ODSByte    fragLoc;
  305.     ODULong    fragOffset;
  306.     ODULong    fragLen;
  307.     ODULong    reserved1;
  308.     ODULong    reserved2;
  309.     ODSShort    infoRecLen;
  310. };
  311.  
  312. struct cfragDescriptor {
  313.     cfragDescHeader header;
  314.     Str255            fragName;
  315. };
  316.  
  317. typedef cfragDescriptor cfragDescriptor;
  318.  
  319. #if PRAGMA_ALIGN_SUPPORTED
  320. #pragma options align=reset
  321. #endif
  322.  
  323. //==============================================================================
  324. // Global Variables
  325. //==============================================================================
  326.  
  327. //==============================================================================
  328. // Local Classes
  329. //==============================================================================
  330.  
  331. class PrefsDirInfo :public Link 
  332. {
  333. public:
  334.     PrefsDirType                fType;            // Type of folder
  335.     ODSShort                    fDepth;            // Nesting depth
  336.     short                        fVol;            // Volume refNum
  337.     long                        fDir;            // Directory ID
  338.     ODULong                        fModDate;        // Dir's mod date when last scanned
  339. };
  340.  
  341.  
  342. //==============================================================================
  343. // Function Prototype
  344. //==============================================================================
  345.  
  346. static ODBoolean GetIndVolume( short index, short *vRefNum );
  347. static ODSLong GetFldrDirID( FSSpec theFolderSpec, ODULong *modDate =kODNULL );
  348. static void GetDirModDateAndParent( short vol, long dir, ODULong *modDate, long *parent );
  349. static ODSize ExtractIText(ODSize bufferPos, ODSession* session, ODValueNameSpace*, ODISOStr key);
  350. static ODSize ExtractISOStringList(ODSize bufferPos, ODSession* session, ODObjectNameSpace*, ODISOStr key);
  351. static ODSize ExtractOSType(ODSize bufferPos, ODSession* session, ODValueNameSpace*, ODISOStr key);
  352. static ODSize ExtractPltfrmTypeSpac(ODSize bufferPos, ODSession* session, ODISOStr key);
  353. static ODSize ExtractISOString(ODSize bufferPos, ODSession* session, ODValueNameSpace*, ODISOStr key);
  354. static void FindMagicFolder( OSType folderType, ConstStr255Param folderName,
  355.                              short *vol, long *dir, ODULong *modDate );
  356. static ODBoolean FindVolumeEditorsFolder( short vol, ConstStr255Param, FSSpec * );
  357. static ODSize ExtractHelpFileName(    ODSize bufferPos, 
  358.                                     ODSession* session, 
  359.                                     const ODFileSpec* fsspec,
  360.                                     ODValueNameSpace *theNameSpace, 
  361.                                     ODISOStr key);
  362. static void Cache_nmap( PlatformFile* cacheFile, ODSize bufferSize, Handle mappingPair,
  363.                                     const FSSpec* );
  364. static void MoveToTrash( short vRefnum, long dirID, Str255 name );
  365. static void    Read_aete_Resources( FSSpec* fsspec, AEDescList* aetes );
  366. static void    AddAETEs(PlatformFile* cacheFile, ODSLong languageCode, AEDescList* aeteList);
  367. static ODBoolean GetODPrefsFolder(ODSShort* prefVol, ODSLong* prefDir );
  368. static OSErr ConstructCacheFileName(ODSShort fldrVRefNum, ODSLong fldrDirID, 
  369.                                       ODULong fldrModDate, Str255* fileName );
  370. static void DeleteOldCacheFiles();
  371. static ODBoolean LoadableLibrary(ODSShort resRefNum);
  372.  
  373. static OSErr ResolveLocalAliasFile(FSSpec *theSpec, Boolean resolveAliasChains, 
  374.                                     Boolean *targetIsFolder, Boolean *wasAliased);
  375.                                     
  376. //==============================================================================
  377. // Class Preferences
  378. //==============================================================================
  379.  
  380. //------------------------------------------------------------------------------
  381. // Preferences::Preferences
  382. //------------------------------------------------------------------------------
  383. Preferences::Preferences()
  384. {
  385.     fSession            = (ODSession*) kODNULL;
  386.     fNameSpaceMgr        = kODNULL;
  387.     fPrefsFile             = (PlatformFile*)kODNULL;
  388.     fPrefsModDate        = 0;
  389.     fDirList            = kODNULL;
  390.     fLastSynchedAt        = 0;
  391.     fPrevSizeRsrc        = kODNULL;
  392.     fScanning            = kODFalse;
  393.     fScanningDialog        = kODNULL;
  394. }
  395.  
  396. //------------------------------------------------------------------------------
  397. // Preferences::~Preferences
  398. //------------------------------------------------------------------------------
  399. Preferences::~Preferences()
  400. {
  401.     ODDeleteObject( fPrefsFile );
  402.     if( fPrevSizeRsrc ) DisposeHandle( fPrevSizeRsrc );
  403.     if( fDirList ) {
  404.         fDirList->DeleteAllLinks();
  405.         delete fDirList;
  406.     }
  407.     WASSERT(fScanningDialog==kODNULL);
  408. }
  409.  
  410. //------------------------------------------------------------------------------
  411. // Preferences::InitPreferences
  412. //------------------------------------------------------------------------------
  413. void Preferences::InitPreferences(ODSession* session)
  414. {
  415.     if( LOGGING ) {
  416.         SetOutputMode(kWriteToDebugWindow);
  417.         LOG("~C");
  418.     }
  419.  
  420.     fSession = session;
  421.     fNameSpaceMgr = fSession->GetNameSpaceManager(somGetGlobalEnvironment());
  422.  
  423.     fDirList = new LinkedList;
  424.     
  425.     ODGetString(fLibsFolderName,   kODLibsFldrNameStrID);
  426.     ODGetString(fEditorsFolderName,kODEditorsFldrNameStrID);
  427.  
  428.         // Create the ContainerSuite, Kind and Category NameSpaces
  429.     CreatePrefsNameSpaces();
  430.  
  431.         // Initialize fPrefsFile and fPrefsfModDate
  432.     GetOpenDocPrefs();
  433.  
  434.     // Don't read the Libraries and Editors folders yet; be lazy about this,
  435.     // they'll be read when needed (ScanLibsAndEditors will be called.)
  436.     
  437.     DeleteOldCacheFiles();
  438. }
  439.  
  440. //------------------------------------------------------------------------------
  441. // Preferences::Purge
  442. //------------------------------------------------------------------------------
  443. ODSize Preferences::Purge(ODSize size)
  444. {
  445. ODUnused(size);
  446.     return 0; //this->ClearEditorNameSpaces();
  447. }
  448.  
  449. //------------------------------------------------------------------------------
  450. // Preferences::GetOpenDoc_nmaps
  451. //------------------------------------------------------------------------------
  452.  
  453. void Preferences::GetOpenDoc_nmaps()
  454. {
  455.     ODSShort libsVRefNum;
  456.     ODSLong libsDirID;
  457.     ODULong libsModDate;
  458.     
  459.         // Load any nmaps found in magic OpenDoc Libraries folder
  460.     TRY{
  461.         FindMagicFolder(kExtensionFolderType,fLibsFolderName,
  462.                         &libsVRefNum,&libsDirID,&libsModDate);
  463.         this->ScanDirectoryTree(libsVRefNum, libsDirID, libsModDate, kLibsFolder);
  464.     }CATCH_ALL{
  465.         THROW(kODErrCannotFindOpenDocLibrariesFolder);
  466.     }ENDTRY
  467. }
  468.  
  469. //------------------------------------------------------------------------------
  470. // Preferences::CreateNameSpaces
  471. //------------------------------------------------------------------------------
  472.  
  473. void Preferences::CreatePrefsNameSpaces()
  474. {
  475.     // This creates the 3 namespaces loaded from Prefs and the container suites.
  476.     
  477.     Environment* ev = somGetGlobalEnvironment ();
  478.     for( ODSLong i=0; i<kNPrefNameSpaces; i++ )
  479.         fNameSpaceMgr->CreateNameSpace(ev, (ODISOStr)kPrefNameSpaces[i].name,
  480.                                            kODNULL,kNumExpectedParts,
  481.                                            kPrefNameSpaces[i].type);
  482. }
  483.  
  484. //------------------------------------------------------------------------------
  485. // Preferences::ClearEditorNameSpaces
  486. //------------------------------------------------------------------------------
  487.  
  488. ODSize Preferences::ClearEditorNameSpaces()
  489. {
  490.     // Clears the namespaces that store the info read from the Editors folders.
  491.     // The other three namespaces are read in from the Prefs file.
  492.  
  493.     size_t oldFreeSpace;
  494.     MMGetFreeSpace(kODNULL,&oldFreeSpace,kODNULL);
  495.     
  496.     Environment* ev = somGetGlobalEnvironment ();
  497.     for( ODSLong i=0; i<kNEditorNameSpaces; i++ ) {
  498.         ODNameSpace *ns = fNameSpaceMgr->HasNameSpace(ev, (ODISOStr)kEditorNameSpaces[i].name);
  499.         if( ns )
  500.             fNameSpaceMgr->DeleteNameSpace(ev,ns);
  501.         ns = fNameSpaceMgr->CreateNameSpace(ev, (ODISOStr)kEditorNameSpaces[i].name,
  502.                                            kODNULL,kNumExpectedParts,
  503.                                            kEditorNameSpaces[i].type);
  504.         ns->SetSynchedToEditors(ev,kODTrue);
  505.     }
  506.     
  507.     fDirList->DeleteAllLinks();
  508.     
  509.     size_t newFreeSpace;
  510.     MMGetFreeSpace(kODNULL,&newFreeSpace,kODNULL);
  511.     newFreeSpace -= oldFreeSpace;
  512.     if( (ODSLong)newFreeSpace < 0 )
  513.         newFreeSpace = 0;
  514.     return newFreeSpace;
  515. }
  516.  
  517.  
  518. //------------------------------------------------------------------------------
  519. // Preferences::ScanDirectoryTree
  520. //------------------------------------------------------------------------------
  521.  
  522. void Preferences::ScanDirectoryTree(ODSShort fldrVRefNum, ODSLong fldrDirID,
  523.                                     ODULong fldrModDate, PrefsDirType type)
  524. {
  525.     LinkedList* dirTreeList = new LinkedList;
  526.     PrefsDirInfo *last = kODNULL;
  527.     PlatformFile* cacheFile = new PlatformFile;
  528.     
  529.         // verify the nmap cache
  530.     ODBoolean cacheIsValid = kODFalse;
  531.     this->VerifyCache(fldrVRefNum, fldrDirID, fldrModDate, type,
  532.                                             &cacheFile, &dirTreeList, &cacheIsValid);
  533.     
  534.         // if the cache is valid, load the cached data
  535.     if ( cacheIsValid )
  536.         cacheIsValid = this->LoadCachedRezData(cacheFile, fldrVRefNum);
  537.         
  538.     if ( !cacheIsValid )
  539.     {
  540.         this->ShowScanningDialog(cacheFile);// Tell user we're updating the list
  541.         
  542.              // empty the list and start over
  543.         if (!dirTreeList->IsEmpty())
  544.             dirTreeList->RemoveAll();
  545.             //    get current mod date of dir id
  546.         ODULong currentModDate;
  547.         long parent;
  548.         GetDirModDateAndParent(fldrVRefNum, fldrDirID, ¤tModDate, &parent);
  549.  
  550.             // add to local list of scanned directories
  551.         PrefsDirInfo *last = this->AddDirInfo(dirTreeList, fldrVRefNum,fldrDirID,
  552.                                                 currentModDate,1,type);
  553.  
  554.         ODSLong    sizeOfLong = sizeof( long );
  555.         ODULong    zero = 0;
  556.         
  557.         while( last ) {
  558.             this->TraverseDirectory(last->fVol,last->fDir, last->fDepth, dirTreeList);
  559.                 // write this directory id and mod date to cache file
  560.             if (cacheFile)
  561.             {
  562.                 cacheFile->Write( (ODSByte*) &last->fDir, &sizeOfLong );
  563.                 cacheFile->Write( (ODSByte*) &last->fModDate , &sizeOfLong );
  564.             }
  565.             last = (PrefsDirInfo*) dirTreeList->After((const Link&)*last);
  566.         }
  567.             // write out 0 to signify end of dir list in cache file
  568.         if (cacheFile)
  569.             cacheFile->Write( (ODSByte*) &zero, &sizeOfLong );
  570.  
  571.             // Loop through directory list loading nmaps and adding nmap data to cache
  572.         PrefsDirInfo *f;
  573.         for( f=(PrefsDirInfo*)dirTreeList->First(); f; 
  574.                                 f=(PrefsDirInfo*)dirTreeList->After(*f) ) 
  575.         {
  576.             this->ScanDirectory(f->fVol,f->fDir, cacheFile);
  577.         }
  578.     }
  579.     
  580.         // Add this local list to the end of fDirList
  581.     this->AddDirList( dirTreeList );
  582.  
  583.     if (!dirTreeList->IsEmpty())
  584.         dirTreeList->DeleteAllLinks();
  585.     ODDeleteObject( dirTreeList );
  586.     
  587.     if (cacheFile)
  588.     {
  589.         cacheFile->Close();
  590.         ODDeleteObject( cacheFile );
  591.     }
  592. }
  593.  
  594. //------------------------------------------------------------------------------
  595. // Preferences::VerifyCache
  596. //------------------------------------------------------------------------------
  597.  
  598. void Preferences::VerifyCache(ODSShort fldrVRefNum, 
  599.                                   ODSLong fldrDirID, 
  600.                                   ODULong fldrModDate,
  601.                                   PrefsDirType type,
  602.                                   PlatformFile** cacheFile,
  603.                                   LinkedList** dirTreeList, 
  604.                                   ODBoolean* cacheIsValid)
  605. {
  606.     *cacheIsValid = kODTrue;
  607.     
  608.         // attempt to locate the fPrefsFile
  609.     if (!GetCacheFile(cacheFile, fldrVRefNum, fldrDirID, fldrModDate) || 
  610.         !LoadCachedDirList(*cacheFile, fldrVRefNum, dirTreeList, type))
  611.     {
  612.             // If a cache file is invalid or cannot be found
  613.             // attempt to delete an existing file if it exists
  614.         TRY{
  615.             if (*cacheFile && (*cacheFile)->Exists())
  616.                 (*cacheFile)->Delete();
  617.         }CATCH_ALL{
  618.             ODDeleteObject (*cacheFile);
  619.         }ENDTRY
  620.             
  621.             // attempt to create a new cache file
  622.         if (*cacheFile)
  623.         {
  624.             TRY{
  625.                 (*cacheFile)->Create(kODShellSignature, 
  626.                                     kPreferencesFolderType, 
  627.                                     smSystemScript );
  628.                                     
  629.             }CATCH_ALL{
  630.                 
  631.                 //CATCH(afpAccessDenied)
  632.                 //CATCH(wPrErr)
  633.                 //CATCH(vLckdErr)
  634.                 //CATCH(dskFulErr)
  635.  
  636.                     // if the cache file cannot be written to volume, create it in prefs
  637.                     // folder
  638.                 Str255 cacheName;
  639.                 ODSShort prefsVol;
  640.                 ODSLong prefsDir;
  641.                 ODFileSpec cacheFileSpec;
  642.  
  643.                 if(GetODPrefsFolder( &prefsVol, &prefsDir ))
  644.                 {
  645.                     OSErr result = ConstructCacheFileName( fldrVRefNum, 
  646.                         fldrDirID, fldrModDate, &cacheName );
  647.                     if (result == noErr)
  648.                     {
  649.                         result = FSMakeFSSpec(prefsVol, prefsDir, cacheName, &cacheFileSpec);
  650.                         if (result == fnfErr )
  651.                         {
  652.                             (*cacheFile)->Specify(&cacheFileSpec);
  653.                             
  654.                             TRY{
  655.                                 (*cacheFile)->Create(kODShellSignature, 
  656.                                                 kPreferencesFolderType, 
  657.                                                 smSystemScript );
  658.                             }CATCH_ALL{
  659.                                 WARN("Error creating cache file");
  660.                 if ((*cacheFile)->Exists())
  661.                     (*cacheFile)->Delete();
  662.                 ODDeleteObject (*cacheFile);
  663.             }ENDTRY
  664.         }
  665.                         else
  666.                             ODDeleteObject (*cacheFile);
  667.                     }
  668.                     else
  669.                         ODDeleteObject (*cacheFile);
  670.                 }
  671.                 else
  672.                     ODDeleteObject (*cacheFile);
  673.  
  674.             }ENDTRY
  675.  
  676.             if (*cacheFile)
  677.             {
  678.                 TRY{
  679.                         // After creating file, make it invisible:
  680.                     ODFileSpec fileSpec = (*cacheFile)->GetFileSpec();
  681.                 FInfo info;
  682.                 if( HGetFInfo(fldrVRefNum,fldrDirID,fileSpec.name,&info) == noErr ) {
  683.                     info.fdFlags |= kIsInvisible;
  684.                     HSetFInfo(fldrVRefNum,fldrDirID,fileSpec.name,&info);
  685.                 }
  686.  
  687.                     (*cacheFile)->Open();
  688.                         // Position mark to beginning of file
  689.                     (*cacheFile)->SetFilePos(fsFromStart, 0);
  690.                     
  691.                 }CATCH_ALL{
  692.                     if ((*cacheFile)->Exists())
  693.                         (*cacheFile)->Delete();
  694.                     ODDeleteObject (*cacheFile);
  695.                 }ENDTRY
  696.             }
  697.         }
  698.             // indicate that cached data is not valid
  699.         *cacheIsValid = kODFalse;
  700.     }
  701. }
  702.  
  703. //------------------------------------------------------------------------------
  704. // Preferences::LoadCachedDirList
  705. //------------------------------------------------------------------------------
  706.  
  707. ODBoolean Preferences::LoadCachedDirList(PlatformFile* cacheFile,
  708.                                           ODSShort fldrVRefNum,
  709.                                           LinkedList** dirTreeList,
  710.                                           PrefsDirType type)
  711. {
  712.     ODBoolean cacheIsValid = kODFalse;
  713.     PrefsDirType flderType = type;
  714.     
  715.     if ((!cacheFile) || (!cacheFile->Exists()))
  716.         return cacheIsValid;
  717.     
  718.     TRY{
  719.         cacheFile->Open();
  720.             // Position mark to beginning of file
  721.         cacheFile->SetFilePos(fsFromStart, 0);
  722.         
  723.         for ( ODSLong fileOffset = 0; 
  724.               fileOffset != cacheFile->GetEndOfFile(); 
  725.               fileOffset = cacheFile->GetFilePos() ) 
  726.         {
  727.             ODULong dirID;
  728.             ODULong modDate;
  729.             ODSLong    sizeoflong = sizeof( long );
  730.             
  731.             //    read in a dir id
  732.             cacheFile->Read( (ODSByte*)&dirID, &sizeoflong );
  733.     
  734.                 //    if 0 is read in, end of cached dir list
  735.             if (dirID == 0)
  736.                 break;
  737.     
  738.                 // read in a modDate
  739.             cacheFile->Read( (ODSByte*)&modDate, &sizeoflong );
  740.     
  741.                 //    get current mod date of dir id
  742.             ODULong currentModDate;
  743.             long parent;
  744.             GetDirModDateAndParent(fldrVRefNum, dirID, ¤tModDate, &parent);
  745.     
  746.                 //    compare it with the one read in
  747.             if (modDate == currentModDate)
  748.             {
  749.                         //Add this dir to linked list
  750.                     PrefsDirInfo *last = kODNULL;
  751.                     last = this->AddDirInfo(*dirTreeList, fldrVRefNum,dirID,modDate,1,flderType );
  752.                     last = (PrefsDirInfo*) (*dirTreeList)->After(*last);
  753.                     flderType = kNestedFolder;
  754.                     cacheIsValid = kODTrue;
  755.             }
  756.             else
  757.             {
  758.                 cacheIsValid = kODFalse;
  759.                 break;
  760.             }
  761.         }
  762.  
  763.         if (!cacheIsValid)
  764.             cacheFile->Close();
  765.         else
  766.         {
  767.                 // Loop through directory list registering each dir with cfm
  768.             PrefsDirInfo *f;
  769.             for( f=(PrefsDirInfo*)(*dirTreeList)->First(); f; 
  770.                                     f=(PrefsDirInfo*)(*dirTreeList)->After(*f) ) 
  771.             {
  772.                 FSSpec folderSpec;
  773.                 OSErr result= FSMakeFSSpec(f->fVol,f->fDir,kODNULL, &folderSpec);
  774.                 if( !result )
  775.                     result= RegisterFileLibs(&folderSpec);
  776. #if ODDebug
  777.                 if( result == noErr)
  778.                     LOG("Registered folder (%hd,%ld)\n",f->fVol,f->fDir);
  779.                 else if( result != fragDupRegLibName && result != fragLibNotFound )
  780.                     WARN("Err %hd registering lib folder (%hd,%ld)",
  781.                             result,f->fVol,f->fDir);
  782. #endif
  783.             }
  784.         }
  785.  
  786.     }CATCH_ALL{
  787.         cacheIsValid = kODFalse;
  788.         cacheFile->Close();
  789.     }ENDTRY
  790.     
  791.     
  792.     return cacheIsValid;
  793.     
  794. }
  795.  
  796. //------------------------------------------------------------------------------
  797. // Preferences::GetCacheFile
  798. //------------------------------------------------------------------------------
  799.  
  800. ODBoolean Preferences::GetCacheFile(PlatformFile** cacheFile, ODSShort fldrVRefNum, 
  801.                                 ODSLong fldrDirID, ODULong fldrModDate )
  802. {
  803.     ODBoolean    cacheFileFound = kODFalse;
  804.     FSSpec        cacheFileSpec;
  805.     
  806.     //Construct an FSSpec
  807.     OSErr result = FSMakeFSSpec(fldrVRefNum, fldrDirID, kODCacheFileName, &cacheFileSpec);
  808.     (*cacheFile)->Specify(&cacheFileSpec);
  809.  
  810.     if (result == noErr)
  811.         cacheFileFound =  kODTrue;
  812.     else
  813.     {
  814.         ODSShort        prefVol;
  815.         ODSLong            prefDir;
  816.         FSSpec            prefCacheFileSpec;
  817.         
  818.         // check prefs folder for a cache file
  819.         if (GetODPrefsFolder( &prefVol, &prefDir ))
  820.         {
  821.             Str255 cacheName;
  822.             result = ConstructCacheFileName( fldrVRefNum, 
  823.                             fldrDirID, fldrModDate, &cacheName );
  824.             if (result == noErr)
  825.                 result = FSMakeFSSpec(prefVol, prefDir, cacheName, &prefCacheFileSpec);
  826.             if (result == noErr )
  827.             {
  828.                 (*cacheFile)->Specify(&prefCacheFileSpec);
  829.                 cacheFileFound =  kODTrue;
  830.             }
  831.         }
  832.     }
  833.  
  834.     return cacheFileFound;
  835. }
  836.  
  837. //------------------------------------------------------------------------------
  838. // Preferences::LoadCachedRezData
  839. //------------------------------------------------------------------------------
  840.  
  841. #define OFFSET(PTR,AMT)        ((void*)( (char*)(PTR)+(AMT) ))
  842.  
  843. #if PRAGMA_ALIGN_SUPPORTED
  844. #pragma options align=mac68k
  845. #endif
  846.  
  847. struct FileLoc {        // File info stored in cache file
  848.     long parID;
  849.     ODSize nameLen;
  850.     char name[64];
  851. };
  852.  
  853. #if PRAGMA_ALIGN_SUPPORTED
  854. #pragma options align=reset
  855. #endif
  856.  
  857. ODBoolean Preferences::LoadCachedRezData(PlatformFile* cacheFile, ODSShort vRefNum)
  858. {
  859.     ODBoolean     validCacheFile = kODTrue;
  860.         
  861.     if (cacheFile)
  862.         TRY{
  863.             ODSize size = cacheFile->GetEndOfFile() - cacheFile->GetFilePos();
  864.             TempODPtr buf = ODNewPtr(size);
  865.             cacheFile->Read(buf,(ODSLong*)&size);
  866.             
  867.             const void* pos = buf;
  868.             const void* const end = OFFSET(pos,size);
  869.             while( pos<end ) {
  870.                 // Read dir ID & filename:
  871.                 const FileLoc *data = (const FileLoc*)pos;
  872.                 pos = OFFSET(pos, sizeof(long) + sizeof(long) + data->nameLen);
  873.                 if( data->nameLen<1 || data->nameLen>63 || pos>end )
  874.                     THROW(kODErrValueOutOfRange);
  875.                 
  876.                 // Construct FSSpec from same:
  877.                 FSSpec spec;
  878.                 spec.vRefNum = vRefNum;
  879.                 spec.parID = data->parID;
  880.                 spec.name[0] = data->nameLen;
  881.                 ODBlockMove(data->name,&spec.name[1],data->nameLen);
  882.                 
  883.                 // Read size of 'nmap' buffer:
  884.                 size = *(ODSize*)pos;
  885.                 pos = OFFSET(pos,sizeof(ODSize));
  886.                 if( pos>end || pos<(void*)buf )
  887.                     THROW(kODErrValueOutOfRange);
  888.                 
  889.                 // Process the 'nmap' data:
  890.                 Read_nmap_Buffer(pos,size,&spec);
  891.                 pos = OFFSET(pos,size);
  892.             }
  893.             
  894.         }CATCH_ALL{
  895.             WARN("Error %d reading nmap cache on volume %hd",ErrorCode(),vRefNum);
  896.             if( ErrorCode() != kODErrOutOfMemory ) {
  897.                 cacheFile->SetEndOfFile(0);
  898.                 validCacheFile = kODFalse;
  899.             }
  900.             // don't propagate exception
  901.     }ENDTRY
  902.     return validCacheFile;
  903. }
  904.  
  905. //------------------------------------------------------------------------------
  906. // Preferences::TraverseDirectory
  907. //------------------------------------------------------------------------------
  908.  
  909. void Preferences::TraverseDirectory( ODSShort fldrVRefNum, ODSLong fldrDirID, 
  910.                                         ODSShort depth, LinkedList* dirList )
  911. {
  912.     CInfoPBRec        pb;
  913.     FSSpec            fileSpec;
  914.     ODBoolean        anyEditors = kODFalse;
  915.     ODError            result;
  916.  
  917.         //check that this is not a bogus folder
  918.     if (fldrDirID == -1)
  919.         return;
  920.     
  921.         // Loop through all the files in folder
  922.     memset (&pb,0,sizeof(pb));
  923.     for( pb.hFileInfo.ioFDirIndex = 1; kODTrue; pb.hFileInfo.ioFDirIndex++ )
  924.     {
  925.         CheckCancelScanningDialog();
  926.             //need to do this each time since PBGetCatInfo call returns val here
  927.         pb.hFileInfo.ioNamePtr = (StringPtr)&fileSpec.name;
  928.         pb.hFileInfo.ioVRefNum = fldrVRefNum;
  929.         pb.hFileInfo.ioDirID = fldrDirID;  
  930.         
  931.         if( PBGetCatInfoSync( &pb ) != noErr )
  932.             break;
  933.         
  934.         if ( (pb.dirInfo.ioFlAttrib & (1<<4)) ) 
  935.         {
  936.             // if this is a folder, append it to the list:
  937.             this->AddDirInfo(dirList, fldrVRefNum, pb.dirInfo.ioDrDirID,
  938.                                          pb.dirInfo.ioDrMdDat,depth+1, kNestedFolder );
  939.         }
  940.         else 
  941.         {
  942.             Boolean    wasAliased = kODFalse;
  943.             fileSpec.vRefNum = pb.hFileInfo.ioVRefNum;
  944.             fileSpec.parID = pb.hFileInfo.ioFlParID;
  945.             
  946.             if ( (pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias) )
  947.             {
  948.                 FSSpec    theSpec;
  949.                 Boolean    targetIsFolder = kODFalse;
  950.                 
  951.                 result = FSMakeFSSpec(fileSpec.vRefNum, fileSpec.parID,
  952.                         fileSpec.name, &theSpec);
  953.                 if (result == noErr)
  954.                 {
  955.                         //resolve alias
  956.                     result = ResolveLocalAliasFile(&theSpec, kODTrue, &targetIsFolder, &wasAliased);
  957.                     if ((result == noErr) && targetIsFolder && (theSpec.vRefNum == fldrVRefNum))
  958.                     {
  959.                         ODULong modDate;
  960.                         long dirID = GetFldrDirID(theSpec,&modDate);
  961.                         this->AddDirInfo(dirList, theSpec.vRefNum, dirID, modDate, depth+1, kNestedFolder);
  962.                     }
  963.                 }
  964.             }
  965.             
  966.         }
  967.     }
  968. }
  969.  
  970.  
  971. //------------------------------------------------------------------------------
  972. // Preferences::ScanDirectory
  973. //------------------------------------------------------------------------------
  974.  
  975. void Preferences::ScanDirectory( ODSShort fldrVRefNum, ODSLong fldrDirID, 
  976.                                                        PlatformFile* cacheFile )
  977. {
  978.     CInfoPBRec        pb;
  979.     FSSpec            fileSpec;
  980.     ODBoolean        anyEditors = kODFalse;
  981.     ODError            result;
  982.     AEDescList        aetes = {typeNull, kODNULL};
  983.     ODSLong            n;
  984.  
  985.         //check that this is not a bogus folder
  986.     if (fldrDirID == -1)
  987.         return;
  988.     
  989.     LOG("Scanning folder (%hd,%ld) for editors...\n", fldrVRefNum,fldrDirID);
  990.  
  991.     THROW_IF_ERROR( AECreateList(kODNULL, 0, kODFalse, &aetes) );
  992.  
  993.     ODSShort saveCurRefNum = CurResFile();
  994.     
  995.         // Loop through all the files in folder
  996.     memset (&pb,0,sizeof(pb));
  997.     for( pb.hFileInfo.ioFDirIndex = 1; kODTrue; pb.hFileInfo.ioFDirIndex++ )
  998.     {
  999.             //need to do this each time since PBGetCatInfo call returns val here
  1000.         pb.hFileInfo.ioNamePtr = (StringPtr)&fileSpec.name;
  1001.         pb.hFileInfo.ioVRefNum = fldrVRefNum;
  1002.         pb.hFileInfo.ioDirID = fldrDirID;  
  1003.         
  1004.         if( PBGetCatInfoSync( &pb ) != noErr )
  1005.             break;
  1006.         
  1007.         Boolean    wasAliased = kODFalse;
  1008.         fileSpec.vRefNum = pb.hFileInfo.ioVRefNum;
  1009.         fileSpec.parID = pb.hFileInfo.ioFlParID;
  1010.         
  1011.         if ( (pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias) )
  1012.         {
  1013.             FSSpec    theSpec;
  1014.             Boolean    targetIsFolder = kODFalse;
  1015.             
  1016.             CheckCancelScanningDialog();
  1017.             result = FSMakeFSSpec(fileSpec.vRefNum, fileSpec.parID,
  1018.                     fileSpec.name, &theSpec);
  1019.             if (result == noErr)
  1020.             {
  1021.                     //resolve alias
  1022.                 result = ResolveLocalAliasFile(&theSpec, kODTrue, &targetIsFolder, &wasAliased);
  1023.                 ODBoolean throwItAway = kODFalse;
  1024.                 if (result == noErr)
  1025.                 {
  1026.                     if (theSpec.vRefNum == fldrVRefNum)
  1027.                     {
  1028.                         if (!targetIsFolder) 
  1029.                         {
  1030.                             if ( pb.hFileInfo.ioFlFndrInfo.fdType == kCFragLibraryFileType ||
  1031.                                 pb.hFileInfo.ioFlFndrInfo.fdType == kODSpecialEditorType) 
  1032.                             {
  1033.                                 // Use the original file of the alias:
  1034.                                 wasAliased = kODTrue;
  1035.                                 fileSpec.vRefNum = theSpec.vRefNum;
  1036.                                 fileSpec.parID = theSpec.parID;
  1037.                                 CopyPascalString(fileSpec.name, theSpec.name);
  1038.                             }
  1039.                         }
  1040.                     }
  1041.                     else
  1042.                         throwItAway = kODTrue;
  1043.                 }
  1044.                 else if (result == nsvErr) // no such volume or server volume
  1045.                     throwItAway = kODTrue;
  1046.             if (throwItAway)
  1047.                 {
  1048.                     // Aliases to targets on other volumes not allowed!!!
  1049.                     // need to alert user!
  1050.                     if ( targetIsFolder || pb.hFileInfo.ioFlFndrInfo.fdType == kCFragLibraryFileType ||
  1051.                         pb.hFileInfo.ioFlFndrInfo.fdType == kODSpecialEditorType) {
  1052.                         MoveToTrash(fileSpec.vRefNum, fileSpec.parID, fileSpec.name);
  1053.                         fFoundBadAlias = kODTrue;
  1054.                     }
  1055.                 }
  1056.             }
  1057.         }
  1058.         
  1059.         if ( pb.hFileInfo.ioFlFndrInfo.fdType == kCFragLibraryFileType ||
  1060.         pb.hFileInfo.ioFlFndrInfo.fdType == kODSpecialEditorType) 
  1061.         {
  1062.             ODBoolean readNMaps = kODFalse;
  1063.             short thisFile = HOpenResFile(fileSpec.vRefNum, fileSpec.parID,
  1064.                     fileSpec.name, fsRdPerm );
  1065.             if (thisFile != -1)
  1066.             {
  1067.                 if (LoadableLibrary(thisFile))
  1068.                 {
  1069.                     // Neither of these routines will throw out of themselves
  1070.                     readNMaps =  Read_nmap_Resources(&fileSpec, cacheFile);
  1071.                     if (readNMaps)
  1072.                         Read_aete_Resources(&fileSpec, &aetes);
  1073.                 }
  1074.                 CloseResFile(thisFile);
  1075.             }
  1076.                 
  1077.             if( /*Adkins -- readNMaps &&*/ (!anyEditors || wasAliased) && 
  1078.             pb.hFileInfo.ioFlFndrInfo.fdType == kCFragLibraryFileType) {
  1079.                 // There are editors in this folder of type kCFragLibraryFileType, so register the folder:
  1080.                 FSSpec folderSpec;
  1081.                 result= FSMakeFSSpec(fileSpec.vRefNum,fileSpec.parID,kODNULL, &folderSpec);
  1082.                 if( !result )
  1083.                     result= RegisterFileLibs(&folderSpec);
  1084. #if ODDebug
  1085.                 if( result == noErr)
  1086.                     LOG("Registered folder (%hd,%ld)\n",fileSpec.vRefNum,fileSpec.parID);
  1087.                 else if( result != fragDupRegLibName && result != fragLibNotFound )
  1088.                     WARN("Err %hd registering lib folder (%hd,%ld)",
  1089.                             result,fileSpec.vRefNum,fileSpec.parID);
  1090. #endif
  1091.                 if( !wasAliased )
  1092.                     anyEditors = kODTrue;
  1093.             }
  1094.         }
  1095.     }
  1096.  
  1097.     THROW_IF_ERROR( AECountItems(&aetes, &n) );
  1098.     if (n != 0)
  1099.     {
  1100.         AEDesc    tempRec;
  1101.         THROW_IF_ERROR( AECreateList(kODNULL, 0, kODTrue, &tempRec) );
  1102.         THROW_IF_ERROR( AEPutKeyDesc(&tempRec, keyDirectObject, &aetes) );
  1103.         HLock(tempRec.dataHandle);
  1104.         cacheFile->WriteResourcePtr(typeAECache, 0, *tempRec.dataHandle, GetHandleSize(tempRec.dataHandle));
  1105.         THROW_IF_ERROR( AEDisposeDesc(&tempRec) );
  1106.     };
  1107.     THROW_IF_ERROR( AEDisposeDesc(&aetes) );
  1108.     
  1109.     UseResFile( saveCurRefNum );
  1110.  
  1111.     LOG("Done scanning folder (%hd,%ld)\n", fldrVRefNum,fldrDirID);
  1112. }
  1113.  
  1114.  
  1115. //------------------------------------------------------------------------------
  1116. // Preferences::FindDirInfo
  1117. //------------------------------------------------------------------------------
  1118.  
  1119. PrefsDirInfo*
  1120. Preferences::FindDirInfo( LinkedList* dirList, short vol, long dir )
  1121. {
  1122.     PrefsDirInfo *e;
  1123.     for( e=(PrefsDirInfo*)dirList->First(); e; e=(PrefsDirInfo*)dirList->After(*e) )
  1124.         if( e->fDir == dir && e->fVol == vol )
  1125.              return e;                        // Already in list, don't add again
  1126.     return kODNULL;
  1127. }
  1128.  
  1129. //------------------------------------------------------------------------------
  1130. // Preferences::AddDirInfo
  1131. //------------------------------------------------------------------------------
  1132.  
  1133. PrefsDirInfo*
  1134. Preferences::AddDirInfo( LinkedList* dirList, short vol, long dir, ODULong modDate, 
  1135.                                 ODSShort depth, PrefsDirType type )
  1136. {
  1137.     if( depth > kMaxDirDepth )
  1138.         return kODNULL;                        // Too deeply nested
  1139.     else if( this->FindDirInfo(dirList, vol,dir ) )
  1140.         return kODNULL;                        // Already in list
  1141.     else {
  1142.         LOG("  Add folder (%hd,%ld) to list.\n", vol,dir);
  1143.     
  1144.         PrefsDirInfo *info = new PrefsDirInfo;
  1145.         info->fType = type;
  1146.         info->fDepth = depth;
  1147.         info->fVol = vol;
  1148.         info->fDir = dir;
  1149.         info->fModDate = modDate;
  1150.         dirList->AddLast(info);
  1151.         return info;
  1152.     }
  1153. }
  1154.  
  1155. //------------------------------------------------------------------------------
  1156. // Preferences::AddDirList
  1157. //------------------------------------------------------------------------------
  1158.  
  1159. void Preferences::AddDirList(LinkedList* dirList)
  1160. {
  1161.     PrefsDirInfo *e;
  1162.     for( e=(PrefsDirInfo*)dirList->First(); e; e=(PrefsDirInfo*)dirList->After(*e) )
  1163.         this->AddDirInfo(fDirList, e->fVol, e->fDir, e->fModDate, e->fDepth, e->fType);
  1164. }
  1165.  
  1166. //------------------------------------------------------------------------------
  1167. // Preferences::Read_nmap_Resources
  1168. //    Utilty routine for reading NMAP resources and creating NameSpaces out of them
  1169. //------------------------------------------------------------------------------
  1170.  
  1171. ODBoolean Preferences::Read_nmap_Resources( const FSSpec *fsspec,
  1172.                                             PlatformFile* cacheFile )
  1173. {
  1174.     ODBoolean readNMaps = kODFalse;
  1175.  
  1176.     LOG("* Reading 'nmap's from file '%P' in (%hd,%ld)\n",fsspec->name,
  1177.             fsspec->vRefNum,fsspec->parID);
  1178.     TRY{
  1179.         ODSShort mappingCount = Count1Resources( kODNameMappings );
  1180.         for (short i=1; i<=mappingCount; i++) 
  1181.         {
  1182.                 // Get the Resource
  1183.             Handle mappingPair = Get1IndResource(kODNameMappings, i);
  1184.             ODError result = ResError();
  1185.             
  1186.             if ( mappingPair != nil && !result )
  1187.             {
  1188.                 ODLockHandle((ODHandle) mappingPair);
  1189.                 
  1190.                 ODSize bufferSize = ODGetHandleSize((ODHandle)mappingPair);
  1191.                 Cache_nmap(cacheFile, bufferSize, mappingPair, fsspec);
  1192.                 Read_nmap_Buffer( (ODPtr)*mappingPair, bufferSize, fsspec );
  1193.                 readNMaps = kODTrue;
  1194.                 
  1195.                 ReleaseResource( mappingPair );
  1196.             }
  1197.         }
  1198.     }CATCH_ALL{
  1199.         WARN("Error %ld reading nmaps for file %#s",ErrorCode(),fsspec->name);
  1200.     }ENDTRY
  1201.     return readNMaps;
  1202. }
  1203.  
  1204. //------------------------------------------------------------------------------
  1205. // Preferences::Read_nmap_Buffer
  1206. //------------------------------------------------------------------------------
  1207.  
  1208. void Preferences::Read_nmap_Buffer(const void* buffer, ODSize bufferSize,
  1209.         const ODFileSpec* fsspec)
  1210. {
  1211.     ODObjectNameSpace *theNameSpace;
  1212.     ODSize            bufferPos=(ODSize)buffer;
  1213.     ODUShort        keyCount;
  1214.     ODUShort        valueType;
  1215.     Environment*     ev = somGetGlobalEnvironment ();
  1216.     
  1217.     ODUShort nameLen = *(ODUShort*)bufferPos;
  1218.     bufferPos += sizeof(ODUShort);
  1219.  
  1220.     TRY
  1221.         TempODISOStr nameSpaceName = 
  1222.             (ODISOStr)ODNewPtrClear((ODSize)nameLen+1, kDefaultHeapID);
  1223.         ODBlockMove((ODPtr)bufferPos, (ODPtr)(ODISOStr)nameSpaceName, (ODSize)nameLen);
  1224.         bufferPos += nameLen;
  1225.         
  1226.         ODBoolean editorAvail = ODISOStrEqual( nameSpaceName, kODEditorUserString );
  1227.         
  1228.         /*    In general, we will get the namespace from the string read here and then pass it
  1229.             to the routine that reads the data. The exception is kODEditorPlatformKind
  1230.             which is not a real namespace, and whose entries are automatically read into
  1231.             the kODEditorKinds namespace. */
  1232.         
  1233.         theNameSpace = (ODObjectNameSpace*)(fNameSpaceMgr->HasNameSpace(ev, nameSpaceName));
  1234.  
  1235.         if( ! theNameSpace && !ODISOStrEqual(nameSpaceName,kODEditorPlatformKind) )
  1236.             WARN("Unknown nmap namespace '%s'", (ODISOStr) nameSpaceName);
  1237.         else {
  1238.             keyCount = *(ODUShort*)bufferPos;
  1239.             bufferPos += sizeof(ODUShort);
  1240.             
  1241.             for(ODUShort i=1; i<= keyCount; i++)
  1242.             {
  1243.                 ODUShort keyLen = *(ODUShort*)bufferPos;
  1244.                 bufferPos += sizeof(ODUShort);
  1245.         
  1246.                 TempODISOStr key = 
  1247.                     (ODISOStr)ODNewPtrClear((ODSize)keyLen+1, kDefaultHeapID);
  1248.                 ODBlockMove((ODPtr)bufferPos, (ODPtr)(ODISOStr)key, (ODSize)keyLen);
  1249.                 bufferPos += (ODSize)keyLen;
  1250.         
  1251.                 if ( editorAvail )
  1252.                 {
  1253.                     // put it in the namespace here....
  1254.                     ODValueNameSpace* editorToFileNS = (ODValueNameSpace*)
  1255.                             (fNameSpaceMgr->HasNameSpace(ev, kODFileFromEditor));
  1256.                     if ( editorToFileNS ) {
  1257.                         ODFileSpec*     prevfsspec;
  1258.                         ODULong            valueLen;
  1259.                         if (ValueNameSpaceGetEntry( editorToFileNS, ev, key,
  1260.                                 (ODPtr*)&prevfsspec, &valueLen )) {
  1261. #if 0
  1262.                             if ((fsspec->vRefNum != prevfsspec->vRefNum) ||
  1263.                                 (fsspec->parID != prevfsspec->parID) ||
  1264.                                 (!EqualPascalStrings(fsspec->name, prevfsspec->name)))
  1265.                             {
  1266.                                 ParamText(fsspec->name, prevfsspec->name, "\p", "\p");
  1267.                                 ODDeleteObject( prevfsspec );
  1268.                                 if (AEInteractWithUser(0, kODNULL, kODNULL) == noErr)
  1269.                                     (void) ShowAlert(ev, kODEditorNmapClashAlertID, kODNULL, fSession);
  1270.                             }
  1271. #endif
  1272.                         }
  1273.                         else
  1274.                             ValueNameSpaceRegister( editorToFileNS, ev, key,
  1275.                                 (ODPtr)fsspec, sizeof(*fsspec) );
  1276.                     }
  1277.                 }
  1278.         
  1279.                 valueType = *(ODUShort*)bufferPos;
  1280.                 bufferPos += sizeof(ODUShort);
  1281.         
  1282.                 switch( valueType )
  1283.                 {
  1284.                         // If the value type is international text read ODName 
  1285.                     case kODIsINTLTextID:
  1286.                         bufferPos = ExtractIText(bufferPos, fSession, 
  1287.                                                 (ODValueNameSpace*)theNameSpace, key);
  1288.                         break;
  1289.                     
  1290.                         // If the value type is an ISOString list read ODTypeList 
  1291.                     case kODIsAnISOStringListID:
  1292.                         bufferPos = ExtractISOStringList(bufferPos, fSession, theNameSpace, key);
  1293.                         break;
  1294.                         
  1295.                         // If the value type is an OSType read ODOSType 
  1296.                     case kODIsMacOSTypeID:
  1297.                         bufferPos = ExtractOSType(bufferPos, fSession,
  1298.                                                     (ODValueNameSpace*)theNameSpace, key);
  1299.                         break;
  1300.                         
  1301.                         // If the value type is an ISOString read ISOString 
  1302.                     case kODIsAnISOStringID:
  1303.                         bufferPos = ExtractISOString(bufferPos, fSession,
  1304.                                                      (ODValueNameSpace*)theNameSpace, key);
  1305.                         break;
  1306.                     
  1307.                         // If the value type is a Platform Type Spec read ODPlatformTypeSpec
  1308.                     case kODIsPltfmTypeSpacID:
  1309.                         bufferPos = ExtractPltfrmTypeSpac(bufferPos, fSession, key);
  1310.                         break;
  1311.                         
  1312.                         // If the value type is a file name for an AppleGuile help file
  1313.                     case kODIsHelpFileNameID:
  1314.                         bufferPos = ExtractHelpFileName(bufferPos, fSession, fsspec,
  1315.                                                     (ODValueNameSpace*)theNameSpace, key);
  1316.                         break;
  1317.                         
  1318.                     default:
  1319.                         break;
  1320.                 }
  1321.             }
  1322.         }
  1323.  
  1324.     CATCH_ALL
  1325.         WARN("Error %ld in Read_nmap_buffer",ErrorCode());
  1326.         RERAISE;
  1327.     ENDTRY
  1328.     
  1329.     return;
  1330. }
  1331.  
  1332. //------------------------------------------------------------------------------
  1333. // Preferences::Write_nmap_Buffer
  1334. //------------------------------------------------------------------------------
  1335.  
  1336. void Preferences::Write_nmap_Buffer(ODPtr buffer, ODSize bufferSize)
  1337. {
  1338. }
  1339.  
  1340. //------------------------------------------------------------------------------
  1341. // Preferences::GetOpenDocPrefs
  1342. //------------------------------------------------------------------------------
  1343.  
  1344. void Preferences::GetOpenDocPrefs( )
  1345. {
  1346.         // attempt to locate the fPrefsFile
  1347.     if (!LocatePrefsFile() || 
  1348.         !VerifyPrefsFileVersion() || 
  1349.         !LoadPreferences())
  1350.     {
  1351.             // If any of the above fail, create the file
  1352.         if (fPrefsFile)
  1353.         {
  1354.             TRY{
  1355.                 fPrefsFile->Create(kODShellSignature, 
  1356.                                     kPreferencesFolderType, 
  1357.                                     smSystemScript );
  1358.                 fPrefsFile->CreateResFile();
  1359.                 fPrefsFile->SetPermission(fsRdWrPerm);
  1360.                 UpdatePrefsFileVersion();
  1361.             }CATCH_ALL{
  1362.                 WARN("Error %ld reading prefs file: deleting it",ErrorCode());
  1363.                 fPrefsFile->Delete();
  1364.                 fPrefsFile = kODNULL;
  1365.             }ENDTRY
  1366.         }
  1367.     }
  1368. }
  1369.  
  1370. //------------------------------------------------------------------------------
  1371. // Preferences::LocatePrefsFile
  1372. //------------------------------------------------------------------------------
  1373.  
  1374. ODBoolean Preferences::LocatePrefsFile()
  1375. {
  1376.     ODError         result;
  1377.     HParamBlockRec    theParamBlock;
  1378.     Str255            prefFileName;
  1379.     ODSShort        prefVol;
  1380.     ODSLong            prefDir;
  1381.     ODFileSpec        prefFileSpec;
  1382.     ODBoolean        retVal = kODFalse;
  1383.  
  1384.     if (!GetODPrefsFolder( &prefVol, &prefDir ))
  1385.         return kODFalse;
  1386.     
  1387.     ODGetString(prefFileName,kODPrefsFileNameStrID);
  1388.  
  1389.         //Construct an FSSpec
  1390.     result = FSMakeFSSpec(prefVol, prefDir, prefFileName, &prefFileSpec);
  1391.                     
  1392.     if (!fPrefsFile)
  1393.     {
  1394.         fPrefsFile = new PlatformFile;
  1395.         TRY{
  1396.             fPrefsFile->Specify(&prefFileSpec);
  1397.         }CATCH_ALL{
  1398.             fPrefsFile->Delete();
  1399.             fPrefsFile = kODNULL;
  1400.             return kODFalse;
  1401.         }ENDTRY
  1402.     }
  1403.  
  1404.         //try to find the file    
  1405.         // if this file does not exists return false
  1406.     if (result) return kODFalse;
  1407.         
  1408.     memset (&theParamBlock,0,sizeof(HParamBlockRec));
  1409.     theParamBlock.fileParam.ioNamePtr = (StringPtr)&prefFileName;
  1410.     theParamBlock.fileParam.ioVRefNum = prefVol;
  1411.     theParamBlock.fileParam.ioFDirIndex = 0;
  1412.     theParamBlock.fileParam.ioDirID = prefDir;
  1413.     if( PBHGetFInfoSync(&theParamBlock) == noErr )
  1414.         fPrefsModDate = theParamBlock.fileParam.ioFlMdDat;
  1415.     return kODTrue;
  1416. }
  1417.  
  1418. //------------------------------------------------------------------------------
  1419. // Preferences::VerifyPrefsFileVersion
  1420. //------------------------------------------------------------------------------
  1421.  
  1422. ODBoolean Preferences::VerifyPrefsFileVersion()
  1423. {
  1424.     ODSShort        result;
  1425.     ODSShort        saveCurRefNum;
  1426.     ODBoolean        retVal=kODFalse;
  1427.     
  1428.             //Get OpenDoc 'vers' resource
  1429.     VersRecHndl odVers;
  1430.     { CUsingLibraryResources r;
  1431.         odVers = (VersRecHndl)Get1Resource( 'vers', 1 );
  1432.         result = ResError();
  1433.         if (odVers )
  1434.             DetachResource((Handle)odVers);
  1435.     }
  1436.     
  1437.     if (odVers )
  1438.     {
  1439.             //Open the resource fork of the Prefs file
  1440.         saveCurRefNum = CurResFile();
  1441.         fPrefsFile->OpenResFile();
  1442.         
  1443.             //Attempt to read 'vers' resource from prefs file
  1444.         VersRecHndl prefVers = (VersRecHndl)Get1Resource('vers', 1);
  1445.         result = ResError();
  1446.         if (!prefVers)
  1447.         {
  1448.             TRY{
  1449.                 fPrefsFile->CloseResFile();
  1450.                 DeletePrefFile();
  1451.             }CATCH_ALL{
  1452.             }ENDTRY
  1453.         }
  1454.         else
  1455.         {
  1456.             ODULong tmp =  kODPrefsCompatiblemajorRev << 24
  1457.                         | kODPrefsCompatibleminorAndBugRev << 16                
  1458.                         | kODPrefsCompatiblestage << 8
  1459.                         | kODPrefsCompatiblenonRelRev;
  1460.  
  1461.             WASSERT( sizeof(ODULong) == sizeof((*prefVers)->numericVersion) );
  1462.             retVal = *((ODULong*)&((*prefVers)->numericVersion)) >= tmp;
  1463.             fPrefsFile->CloseResFile();
  1464.             
  1465.             if ( !retVal )
  1466.                 fPrefsFile->Delete();
  1467.         }
  1468.                 
  1469.         DisposeHandle((Handle)odVers);
  1470.         UseResFile( saveCurRefNum );
  1471.     }
  1472.  
  1473.     return retVal;
  1474. }
  1475.  
  1476. //------------------------------------------------------------------------------
  1477. // Preferences::LoadPreferences
  1478. //------------------------------------------------------------------------------
  1479.  
  1480. ODBoolean Preferences::LoadPreferences()
  1481. {
  1482.     ODULong            nameSpaceNameLength;
  1483.     ODISOStr        nameSpaceName;
  1484.     ODValueNameSpace*     theNameSpace;
  1485.     Environment*     ev = somGetGlobalEnvironment ();
  1486.     
  1487.  
  1488.         // If there is a pref file, open it
  1489.     if (fPrefsFile)
  1490.     {
  1491.         TRY{
  1492.             fPrefsFile->Open();
  1493.             
  1494.                 // Position mark to beginning of file
  1495.             fPrefsFile->SetFilePos(fsFromStart, 0);
  1496.             
  1497.             for ( ODSLong fileOffset = 0; 
  1498.                   fileOffset != fPrefsFile->GetEndOfFile(); 
  1499.                   fileOffset = fPrefsFile->GetFilePos() ) 
  1500.             {
  1501.                     // Get each "mapping"
  1502.                 nameSpaceNameLength = ReadSize(fPrefsFile, 
  1503.                                                    (ODStorageUnitView*)kODNULL);
  1504.                 nameSpaceName = (ODISOStr)ODNewPtrClear(nameSpaceNameLength+1,
  1505.                                                                 kDefaultHeapID);
  1506.                 TRY{
  1507.                     ReadBytes(fPrefsFile,
  1508.                                     (ODStorageUnitView*)kODNULL, nameSpaceName, 
  1509.                                     &nameSpaceNameLength);
  1510.                     theNameSpace = (ODValueNameSpace*)fNameSpaceMgr->HasNameSpace(ev,
  1511.                                                                         nameSpaceName);
  1512.                     // Create the namespace if it's unknown  --jpa
  1513.                     if( !theNameSpace ) {
  1514.                         WARN("Unknown namespace '%s' in prefs",nameSpaceName);
  1515.                         theNameSpace = (ODValueNameSpace*)
  1516.                                 fNameSpaceMgr->CreateNameSpace(ev,nameSpaceName,
  1517.                                                             kODNULL,kNumExpectedParts,
  1518.                                                             kODNSDataTypeODValue);
  1519.                     }
  1520.                     ValueNameSpaceReadFromFile(theNameSpace, fPrefsFile);
  1521.                         
  1522.                 }CATCH_ALL{
  1523.                     ODDisposePtr(nameSpaceName);
  1524.                     RERAISE;
  1525.                 }ENDTRY
  1526.  
  1527.                 ODDisposePtr(nameSpaceName);
  1528.             }
  1529.     
  1530.             fPrefsFile->Close();
  1531.     
  1532.         }CATCH_ALL{
  1533.             fPrefsFile->Close();
  1534.             DeletePrefFile();
  1535.             return kODFalse;
  1536.         }ENDTRY
  1537.         
  1538.         return kODTrue;
  1539.     }
  1540.     else
  1541.         return kODFalse;
  1542. }
  1543.  
  1544. //------------------------------------------------------------------------------
  1545. // Preferences::UpdatePreferences
  1546. //------------------------------------------------------------------------------
  1547.  
  1548. void Preferences::UpdatePreferences()
  1549. {
  1550.     ODValueNameSpace*    theNameSpace=kODNULL;
  1551.     ODSLong            sizeLong = sizeof(ODULong);
  1552.     Environment*     ev = somGetGlobalEnvironment ();
  1553.                 
  1554.     // If there is a pref file and it is writable, update it
  1555.     if (fPrefsFile && (!fPrefsFile->IsLocked()))
  1556.     {
  1557.             // Open the file
  1558.         fPrefsFile->Open();
  1559.         
  1560.             // Release current contents of file
  1561.         fPrefsFile->SetEndOfFile( 0 );
  1562.         
  1563.             // Position mark to beginning of file
  1564.         fPrefsFile->SetFilePos(fsFromStart, 0);
  1565.  
  1566.             // Get SysPrefEditorKinds nameSpace
  1567.         ODValueNameSpace* sysPrefEditorKindsNameSpace = (ODValueNameSpace*)
  1568.             fNameSpaceMgr->HasNameSpace( ev,
  1569.                                          kODSysPrefEditorKinds );
  1570.  
  1571.         if (sysPrefEditorKindsNameSpace != kODNULL)
  1572.         {
  1573.             TempODISOStr nsName = sysPrefEditorKindsNameSpace->GetName(ev); // ensure deletion
  1574.             ODULong nsNameLength = ODISOStrLength((ODISOStr) nsName);
  1575.  
  1576.                 // write length of name of name space to prefs
  1577.             fPrefsFile->Write( (const ODSByte*)&nsNameLength, &sizeLong );
  1578.                 // write name of name space to prefs
  1579.             fPrefsFile->Write( (const ODSByte*) (ODISOStr) nsName, (ODSLong*)&nsNameLength );
  1580.                 // write out entire namespace to prefs
  1581.             ValueNameSpaceWriteToFile( sysPrefEditorKindsNameSpace, fPrefsFile );
  1582.         }
  1583.  
  1584.             // Get SysPrefEditorCategories nameSpace
  1585.         ODValueNameSpace* sysPrefEditorCategoriesNameSpace = 
  1586.             (ODValueNameSpace*)(fNameSpaceMgr->
  1587.                                     HasNameSpace(ev, kODSysPrefEditorCategories ));
  1588.  
  1589.         if (sysPrefEditorCategoriesNameSpace != kODNULL)
  1590.         {
  1591.             TempODISOStr nsName = sysPrefEditorCategoriesNameSpace->GetName(ev); // ensure deletion
  1592.             ODULong nsNameLength = ODISOStrLength((ODISOStr) nsName);
  1593.  
  1594.                 // write length of name of name space to prefs
  1595.             fPrefsFile->Write( (const ODSByte*) &nsNameLength, &sizeLong );
  1596.                 // write name of name space to prefs
  1597.             fPrefsFile->Write( (const ODSByte*) (ODISOStr) nsName, (ODSLong*)&nsNameLength );
  1598.                 // write out entire namespace to prefs
  1599.             ValueNameSpaceWriteToFile( sysPrefEditorCategoriesNameSpace, fPrefsFile );
  1600.         }
  1601.  
  1602.             // Get SysPrefContainerSuites nameSpace
  1603.         ODValueNameSpace* containerSuiteNameSpace = (ODValueNameSpace*)
  1604.             (fNameSpaceMgr->HasNameSpace( ev, kODSysPrefContainerSuites ));
  1605.  
  1606.         if (containerSuiteNameSpace != kODNULL)
  1607.         {
  1608.             TempODISOStr nsName = containerSuiteNameSpace->GetName(ev); // ensure deletion
  1609.             ODULong nsNameLength = ODISOStrLength((ODISOStr) nsName);
  1610.  
  1611.                 // write length of name of name space to prefs
  1612.             fPrefsFile->Write( (const ODSByte*) &nsNameLength, &sizeLong );
  1613.                 // write name of name space to prefs
  1614.             fPrefsFile->Write( (const ODSByte*) (ODISOStr) nsName, (ODSLong*)&nsNameLength );
  1615.                 // write out entire namespace to prefs
  1616.             ValueNameSpaceWriteToFile( containerSuiteNameSpace, fPrefsFile );
  1617.         }
  1618.         
  1619.             // Close the file
  1620.         fPrefsFile->Close();
  1621.     }
  1622.     else
  1623.         WARN("Prefs file does not exist or is readonly");
  1624. }
  1625.  
  1626. //------------------------------------------------------------------------------
  1627. // Preferences::UpdatePrefsFileVersion
  1628. //------------------------------------------------------------------------------
  1629.  
  1630. void Preferences::UpdatePrefsFileVersion()
  1631. {
  1632.     OSErr            result;
  1633.     ODSShort        saveCurRefNum;
  1634.  
  1635.         //Get OpenDoc 'vers' resource
  1636.     ODSLong         savedRefNum;
  1637.     BeginUsingLibraryResources(savedRefNum);
  1638.  
  1639.     Handle odVers = Get1Resource( 'vers', 1 );
  1640.     result = ResError();
  1641.     if (odVers) {
  1642.         DetachResource(odVers);
  1643.         result = ResError();
  1644.     } else
  1645.         if( result==noErr ) result=resNotFound;
  1646.  
  1647.     EndUsingLibraryResources(savedRefNum);
  1648.     
  1649.     THROW_IF_ERROR(result);
  1650.     
  1651.         //Open the resource fork of the Prefs file
  1652.     saveCurRefNum = CurResFile();
  1653.     fPrefsFile->OpenResFile();
  1654.         //Write OpenDoc 'vers' resource to prefs file
  1655.     Handle prefVers = Get1Resource( 'vers', 1 );
  1656.     if (prefVers==kODNULL) {
  1657.         result= ResError();
  1658.         if( result==noErr || result==resNotFound ) {
  1659.             AddResource(odVers, 'vers', 1, "\p");
  1660.             result= ResError();
  1661.         }
  1662.         if( !result )
  1663.             odVers = kODNULL;    // It's been adopted by fPrefsFile
  1664.     } else {
  1665.         Size odSize = GetHandleSize(odVers);
  1666.         SetHandleSize(prefVers, odSize);
  1667.         result= MemError();
  1668.         if( !result ) {
  1669.             ODBlockMove(*odVers,*prefVers,odSize);
  1670.             ChangedResource(prefVers);
  1671.             result = ResError();
  1672.         }
  1673.     }
  1674.     // if we have a size resource in prev pref file, use it in new one
  1675.     if (fPrevSizeRsrc) {    
  1676.         AddResource(fPrevSizeRsrc, 'SIZE', -1, "\p");
  1677.         if( !ResError() )
  1678.             fPrevSizeRsrc = kODNULL;    // It's been adopted by fPrefsFile
  1679.     }
  1680.     fPrefsFile->CloseResFile();
  1681.     UseResFile( saveCurRefNum );
  1682.     if( odVers ) DisposeHandle( odVers );
  1683.     if( fPrevSizeRsrc ) {
  1684.         DisposeHandle( fPrevSizeRsrc );
  1685.         fPrevSizeRsrc = kODNULL;
  1686.     }
  1687.     THROW_IF_ERROR(result);
  1688. }
  1689.  
  1690. //------------------------------------------------------------------------------
  1691. // Preferences::DeletePrefFile
  1692. //------------------------------------------------------------------------------
  1693.  
  1694. void Preferences::DeletePrefFile()
  1695. {
  1696.     ODSShort        saveCurRefNum;
  1697.     
  1698.     TRY
  1699.             // Open the resource fork of the Prefs file
  1700.         saveCurRefNum = CurResFile();
  1701.         fPrefsFile->OpenResFile();
  1702.             // read its size resource for future use
  1703.         if( fPrevSizeRsrc ) DisposeHandle( fPrevSizeRsrc );
  1704.         fPrevSizeRsrc = Get1Resource( 'SIZE', -1 );
  1705.         if (fPrevSizeRsrc)
  1706.             DetachResource(fPrevSizeRsrc);
  1707.         fPrefsFile->CloseResFile();
  1708.         UseResFile( saveCurRefNum );
  1709.         fPrefsFile->Delete();
  1710.         if (AEInteractWithUser(0, kODNULL, kODNULL) == noErr)
  1711.             (void) ShowAlert(kODNULL, kODEditorPrefsDamagedAlertID, kODNULL, fSession);
  1712.     CATCH_ALL
  1713.     ENDTRY
  1714. }
  1715.  
  1716. //------------------------------------------------------------------------------
  1717. // Preferences::HaveEditorsFoldersChanged
  1718. //------------------------------------------------------------------------------
  1719.  
  1720. ODBoolean Preferences::HaveEditorsFoldersChanged()
  1721. {
  1722.     if( fScanning )
  1723.         return kODFalse;            // Skip re-entrant scans
  1724.         
  1725.     // Don't even scan folders more often than once every kMinResynchTime ticks:
  1726.     if( (ODULong)(TickCount() - fLastSynchedAt) <= kMinResynchTime )
  1727.         return kODFalse;
  1728.         
  1729.     // First find the current Editors folder in the System folder:
  1730.     FSSpec editorsSpec;
  1731.     ODULong editorsModDate;
  1732.     TRY{
  1733.         FindMagicFolder(kSystemFolderType,fEditorsFolderName,
  1734.                             &editorsSpec.vRefNum,&editorsSpec.parID,&editorsModDate);
  1735.     }CATCH_ALL{
  1736.         WARN("Error %ld reading system editors folder",ErrorCode());
  1737.         THROW(kODErrCannotFindSystemEditorsFolder);
  1738.     }ENDTRY
  1739.  
  1740.     // Check if any of the scanned folders have had their mod date bumped or are deleted:
  1741.     ODBoolean foundSysEditorsFolder = kODFalse;
  1742.     PrefsDirInfo *f;
  1743.     for( f=(PrefsDirInfo*)fDirList->First(); f; f=(PrefsDirInfo*)fDirList->After(*f) ) {
  1744.         ODULong modDate;
  1745.         long parent;
  1746.         GetDirModDateAndParent(f->fVol,f->fDir, &modDate,&parent);
  1747.         
  1748.         if( modDate != f->fModDate )
  1749.             return kODTrue;                        // Folder's been changed
  1750.         else if( f->fType==kRootEditorsFolder ) {
  1751.             if( parent != fsRtDirID )
  1752.                 return kODTrue;                    // Root editors folder's been moved
  1753.         } else if( f->fType==kSysEditorsFolder ) {
  1754.             if( f->fDir != editorsSpec.parID )
  1755.                 return kODTrue;                    // Sys editors folder not same as current one
  1756.             foundSysEditorsFolder = kODTrue;
  1757.         }
  1758.     }
  1759.     
  1760.     // If the current sys editors folder isn't in the list, something's changed:
  1761.     if( !foundSysEditorsFolder )
  1762.         return kODTrue;
  1763.     
  1764.     // Look for each vol's Editors folder and see if it's a different folder:
  1765.     short vol;
  1766.     for( ODSShort vIndex=1; GetIndVolume(vIndex,&vol); vIndex++ )
  1767.         if( vol != 0 ) {
  1768.             TRY{
  1769.                 if( FindVolumeEditorsFolder(vol,fEditorsFolderName,&editorsSpec) ) {
  1770.                     if( !this->FindDirInfo(fDirList, vol,GetFldrDirID(editorsSpec)) )
  1771.                         return kODTrue;
  1772.                 }
  1773.             }CATCH_ALL{
  1774.                 return kODTrue;
  1775.             }ENDTRY
  1776.         }
  1777.     
  1778.     fLastSynchedAt = TickCount();                // Don't check again for another few seconds
  1779.     return kODFalse;
  1780. }
  1781.  
  1782. //------------------------------------------------------------------------------
  1783. // Preferences::ScanLibsAndEditors
  1784. //------------------------------------------------------------------------------
  1785.  
  1786. ODBoolean Preferences::ScanLibsAndEditors()
  1787. {
  1788.     /* First, check whether the Editors folders have changed. If not, do nothing.
  1789.        Also disable this routine completely if it's being called re-entrantly, by
  1790.        checking the fScanning flag. This is quite likely to happen because the
  1791.        namespace manager calls me anytime anyone asks for any of the editor name-
  1792.        spaces, which is something I do when rebuilding them. */
  1793.        
  1794.     if( ! this->HaveEditorsFoldersChanged() )
  1795.         return kODFalse;
  1796.     
  1797.     fScanning = kODTrue;
  1798.     fFoundBadAlias = kODFalse;
  1799.     
  1800.     TRY{
  1801.         FSSpec editorsSpec;
  1802.         
  1803.         // Clear out the name spaces, we're starting from scratch:
  1804.         this->ClearEditorNameSpaces();
  1805.         
  1806.         // First search all 'nmap's in the OpenDoc Libraries folder:
  1807.         this->GetOpenDoc_nmaps();
  1808.         
  1809.         if( fFoundBadAlias ) {
  1810.             // Tell user she can't put aliases to other volumes in an Library folder.
  1811.             // I've avoided using a filterProc to avoid re-entrancy problems since who
  1812.             // knows who might have triggered this scan by innocently asking for a
  1813.             // namespace? --jpa
  1814.             if (AEInteractWithUser(0, kODNULL, kODNULL) == noErr)
  1815.                 (void) ShowAlert(kODNULL, kODBadAliasInLibrariesAlertID, kODNULL, fSession);
  1816.             fFoundBadAlias = kODFalse;
  1817.         }
  1818.  
  1819.         // Search the "Editors" folder in the System folder:
  1820.         TRY{
  1821.                 ODULong editorsModDate;
  1822.                 FindMagicFolder(kSystemFolderType,fEditorsFolderName,
  1823.                                     &editorsSpec.vRefNum,&editorsSpec.parID,&editorsModDate);
  1824.                 this->ScanDirectoryTree(editorsSpec.vRefNum,editorsSpec.parID,
  1825.                                         editorsModDate,kSysEditorsFolder);
  1826.         }CATCH_ALL{
  1827.             if( ErrorCode()==userCanceledErr )
  1828.                 RERAISE;
  1829.             WARN("Error %ld reading system editors folder",ErrorCode());
  1830.             THROW(kODErrCannotFindSystemEditorsFolder);
  1831.         }ENDTRY
  1832.         
  1833.         // Now for each mounted volume, find and search its "Editors" folder:
  1834.         short vol;
  1835.         for( ODSShort vIndex=1; GetIndVolume(vIndex,&vol); vIndex++ )
  1836.             if( vol != 0 ) {
  1837.                 TRY{
  1838.                         if( FindVolumeEditorsFolder(vol,fEditorsFolderName,&editorsSpec) ) {
  1839.                             ODULong modDate;
  1840.                             ODSLong dir = GetFldrDirID(editorsSpec,&modDate);
  1841.                             this->ScanDirectoryTree( vol, dir, modDate, kRootEditorsFolder );
  1842.                     }
  1843.                 }CATCH_ALL{
  1844.                     WARN("Error %ld reading root editors folder on volume %hd",ErrorCode(),vol);
  1845.                 }ENDTRY
  1846.             }
  1847.         
  1848.         fLastSynchedAt = ::TickCount();
  1849.         fScanning = kODFalse;
  1850.         this->CloseScanningDialog();
  1851.         
  1852.     }CATCH_ALL{
  1853.         fScanning = kODFalse;
  1854.         this->CloseScanningDialog();
  1855.         RERAISE;
  1856.     }ENDTRY
  1857.     
  1858.     if( fFoundBadAlias ) {
  1859.         // Tell user she can't put aliases to other volumes in an Editors folder.
  1860.         // I've avoided using a filterProc to avoid re-entrancy problems since who
  1861.         // knows who might have triggered this scan by innocently asking for a
  1862.         // namespace? --jpa
  1863.         if (AEInteractWithUser(0, kODNULL, kODNULL) == noErr)
  1864.             (void) ShowAlert(kODNULL, kODBadAliasInEditorsAlertID, kODNULL, fSession);
  1865.     }
  1866.     
  1867.     return kODTrue;
  1868. }
  1869.  
  1870. //------------------------------------------------------------------------------
  1871. // Preferences::ShowScanningDialog
  1872. //------------------------------------------------------------------------------
  1873.  
  1874. void
  1875. Preferences::ShowScanningDialog(PlatformFile* cacheFile)
  1876. {
  1877.     fCacheFile = cacheFile;
  1878.     if( !fScanningDialog ) {
  1879.         fProgressPictIndex = 0;
  1880.         fSleepTime = 0;
  1881.         CUsingLibraryResources r;
  1882.         fScanningDialog = ::GetNewDialog(kODScanEditorsDialogID,kODNULL,(WindowPtr)-1L);
  1883.         ::ShowWindow(fScanningDialog);
  1884.         ::DrawDialog(fScanningDialog);
  1885.         ::SetCursor(&(ODQDGlobals.arrow));
  1886.         for (ODUShort i=0;i<4;i++) {
  1887.             TRY {
  1888.                 fProgresstPictHdl[i] = ODReadResource(kPICTRsrcType, kScanEditorsProgressBarID+i);
  1889.             }CATCH_ALL{
  1890.                 fProgresstPictHdl[i] = kODNULL;
  1891.             }ENDTRY
  1892.         }
  1893.         ODHandle    dummy;
  1894.         short        dummyType;
  1895.         GetDialogItem(fScanningDialog, kScanEditorsStopButton, &dummyType, &fButtonControl, &fProgressItemRect);
  1896.         GetDialogItem(fScanningDialog, kScanEditorsProgressItem, &dummyType, &dummy, &fProgressItemRect);
  1897.         fProgressItemRgn = ODNewRgn();
  1898.         if (fProgressItemRgn) {
  1899.             RectRgn(fProgressItemRgn,&fProgressItemRect);
  1900.         }
  1901.     }
  1902. }
  1903.  
  1904. //------------------------------------------------------------------------------
  1905. // Preferences::CloseScanningDialog
  1906. //------------------------------------------------------------------------------
  1907.  
  1908. void
  1909. Preferences::CloseScanningDialog( )
  1910. {
  1911.     if( fScanningDialog ) {
  1912.         CUsingLibraryResources r;
  1913.         ::DisposeDialog(fScanningDialog);
  1914.         fScanningDialog = kODNULL;
  1915.         for (ODUShort i=0;i<4;i++)
  1916.             ODDisposeHandle(fProgresstPictHdl[i]);
  1917.         ODDisposeHandle((Handle)fProgressItemRgn);
  1918.     }
  1919. }
  1920.  
  1921. //------------------------------------------------------------------------------
  1922. // Preferences::CheckCancelScanningDialog
  1923. //------------------------------------------------------------------------------
  1924.  
  1925. void
  1926. Preferences::CheckCancelScanningDialog( )
  1927. {
  1928.     short        itemHit = 0;
  1929.     char        key;
  1930.     
  1931.     if( fScanningDialog ) {
  1932.         if (++fProgressPictIndex==4)
  1933.             fProgressPictIndex=0;
  1934.  
  1935.         if (fProgressItemRgn && fProgresstPictHdl[fProgressPictIndex]) {
  1936.             SetPort(fScanningDialog);        
  1937.             SetDialogItem(fScanningDialog, kScanEditorsProgressItem, itemDisable+picItem, fProgresstPictHdl[fProgressPictIndex], &fProgressItemRect);
  1938.             UpdateDialog(fScanningDialog, fProgressItemRgn);
  1939.         }
  1940.  
  1941.         EventRecord     theEvent;
  1942.         if (WaitNextEvent(mDownMask+keyDownMask+autoKeyMask+updateMask+osMask, &theEvent, fSleepTime, kODNULL)) {
  1943.             itemHit = 0;
  1944.             switch( theEvent.what )
  1945.                 {
  1946.                     case updateEvt:
  1947.                         if ((WindowPtr)theEvent.message == fScanningDialog) {
  1948.                             ::BeginUpdate(fScanningDialog);
  1949.                             ::DrawDialog(fScanningDialog);
  1950.                             ::EndUpdate(fScanningDialog);
  1951.                         }
  1952.                         else {
  1953.                             TRY{
  1954.                                 Environment* ev = somGetGlobalEnvironment ();
  1955.                                 ODDispatcher* dispatcher = fSession->GetDispatcher(ev);
  1956.                                 if (dispatcher)
  1957.                                     dispatcher->Dispatch(ev, (ODEventData*)&theEvent);
  1958.                             }CATCH_ALL{
  1959.                             }ENDTRY
  1960.                         }
  1961.                         break;
  1962.                     case osEvt:
  1963.                         if( (( theEvent.message >> 24 ) & 0x00FF)==suspendResumeMessage )
  1964.                             if (theEvent.message & resumeFlag) {
  1965.                                 fSleepTime = 0;
  1966.                                 HiliteControl((ControlHandle)fButtonControl, 0);
  1967.                             }
  1968.                             else {
  1969.                                 fSleepTime = 10;
  1970.                                 HiliteControl((ControlHandle)fButtonControl, 255);
  1971.                             }
  1972.                         break;
  1973.                     case keyDown:
  1974.                     case autoKey:
  1975.                         key = (theEvent.message & charCodeMask);
  1976.                         if ((key == 0x1B) || ((theEvent.modifiers & cmdKey) && (key == '.')))
  1977.                             itemHit = kScanEditorsStopButton;
  1978.                         else
  1979.                             SysBeep(0);
  1980.                         break;
  1981.                     case mouseDown:
  1982.                         if (IsDialogEvent(&theEvent))
  1983.                             (void) DialogSelect(&theEvent, &fScanningDialog, &itemHit);
  1984.                         else {
  1985.                             WindowPtr        theWindow;
  1986.                             short            part;
  1987.                             
  1988.                             part = FindWindow(theEvent.where, &theWindow);
  1989.                             if ((part == inDrag) && (theWindow == fScanningDialog)) {
  1990.                                 Rect bounds = ODQDGlobals.screenBits.bounds;
  1991.                                 DragWindow(theWindow,theEvent.where,&bounds);
  1992.                             }
  1993.                             else
  1994.                                 SysBeep(30);
  1995.                         }
  1996.                     default:
  1997.                         break;
  1998.                 }
  1999.             if (itemHit == kScanEditorsStopButton) {
  2000.                 long dummyTime;
  2001.                 HiliteControl((ControlHandle)fButtonControl, kControlButtonPart);
  2002.                 Delay(8, &dummyTime);    // give visual feedback to user
  2003.                 HiliteControl((ControlHandle)fButtonControl, 0);
  2004.                 CloseScanningDialog();
  2005.                 // We are in middle of writing to the cache file, better delete it to start over
  2006.                 TRY {
  2007.                     fCacheFile->Close();
  2008.                     fCacheFile->Delete();
  2009.                 }CATCH_ALL{
  2010.                 }ENDTRY
  2011.                 THROW(userCanceledErr);
  2012.             };
  2013.         
  2014.         }
  2015.     }
  2016. }
  2017.  
  2018.  
  2019. void
  2020. Preferences::GetAETEs( ODSLong languageCode, AEDescList* aeteList)
  2021. {
  2022.     /*    First, make sure the cache is up to date, which should be a noop. 
  2023.      *    Then walk the Editors Folder cache files and accumulate aete resources
  2024.      *    with the proper language code and return them in the aeteList.
  2025.      */
  2026.        
  2027.     FSSpec editorsSpec;
  2028.     PlatformFile* cacheFile = kODNULL;
  2029.  
  2030.     this->ScanLibsAndEditors();
  2031.     cacheFile = new PlatformFile;
  2032.     
  2033.     TRY
  2034.         // Search the "Editors" folder in the System folder:
  2035.         TRY{
  2036.                 ODULong editorsModDate;
  2037.                 FindMagicFolder(kSystemFolderType, fEditorsFolderName,
  2038.                         &editorsSpec.vRefNum, &editorsSpec.parID, &editorsModDate);
  2039.                 this->GetCacheFile(&cacheFile, editorsSpec.vRefNum, editorsSpec.parID, editorsModDate);
  2040.                 AddAETEs(cacheFile, languageCode, aeteList);
  2041.         }CATCH_ALL{
  2042.             WARN("Error %ld reading system editors folder",ErrorCode());
  2043.             THROW(kODErrCannotFindSystemEditorsFolder);
  2044.         }ENDTRY
  2045.         
  2046.         // Now for each mounted volume, find and search its "Editors" folder:
  2047.         short vol;
  2048.         for( ODSShort vIndex=1; GetIndVolume(vIndex,&vol); vIndex++ )
  2049.             if( vol != 0 ) {
  2050.                 TRY{
  2051.                     if( FindVolumeEditorsFolder(vol, fEditorsFolderName, &editorsSpec) ) {
  2052.                         ODULong modDate;
  2053.                         ODSLong dir = GetFldrDirID(editorsSpec, &modDate);
  2054.                         this->GetCacheFile(&cacheFile, vol, dir, modDate);
  2055.                         AddAETEs(cacheFile, languageCode, aeteList);
  2056.                     }
  2057.                 }CATCH_ALL{
  2058.                     WARN("Error %ld reading root editors folder on volume %hd",ErrorCode(),vol);
  2059.                 }ENDTRY
  2060.             }
  2061.     CATCH_ALL
  2062.         ODDeleteObject(cacheFile);
  2063.         RERAISE;
  2064.     ENDTRY
  2065.     ODDeleteObject(cacheFile);
  2066. }    // GetAETEs
  2067.  
  2068.  
  2069. //------------------------------------------------------------------------------
  2070. // GetPrefsFile
  2071. //------------------------------------------------------------------------------
  2072. PlatformFile* Preferences::GetPrefsFile()
  2073. {
  2074.     return fPrefsFile;
  2075. }
  2076.  
  2077. //------------------------------------------------------------------------------
  2078. // FindMagicFolder
  2079. //------------------------------------------------------------------------------
  2080. static void FindMagicFolder( OSType folderType, ConstStr255Param folderName,
  2081.                              short *vol, long *dir, ODULong *modDate )
  2082. {
  2083.     CInfoPBRec        pb;
  2084.     memset (&pb,0,sizeof(pb));
  2085.  
  2086.     THROW_IF_ERROR( FindFolder(kOnSystemDisk, folderType, kDontCreateFolder, 
  2087.                                 &pb.dirInfo.ioVRefNum, &pb.dirInfo.ioDrDirID) );
  2088.     Str63 name;
  2089.     CopyPascalString(name,folderName);
  2090.     pb.dirInfo.ioNamePtr = name;
  2091.     pb.dirInfo.ioFDirIndex = 0;
  2092.     THROW_IF_ERROR( PBGetCatInfoSync( &pb ) );
  2093.     
  2094.     if( pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias ) {
  2095.         FSSpec spec;
  2096.         ODBoolean targetIsFolder, wasAliased;
  2097.         FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,name, &spec);
  2098.         THROW_IF_ERROR( ResolveAliasFile(&spec, kODTrue, &targetIsFolder, &wasAliased) );
  2099.         if( !targetIsFolder )
  2100.             THROW(dirNFErr);
  2101.         // Now get dir ID of target folder:
  2102.         pb.dirInfo.ioNamePtr = spec.name;
  2103.         pb.dirInfo.ioFDirIndex = 0;
  2104.         pb.dirInfo.ioVRefNum = spec.vRefNum;
  2105.         pb.dirInfo.ioDrDirID = spec.parID;
  2106.         THROW_IF_ERROR( PBGetCatInfoSync( &pb ) );
  2107.     }
  2108.     
  2109.     *vol = pb.dirInfo.ioVRefNum;
  2110.     *dir = pb.dirInfo.ioDrDirID;
  2111.     *modDate = pb.dirInfo.ioDrMdDat;
  2112. }
  2113.  
  2114. //------------------------------------------------------------------------------
  2115. // FindVolumeEditorsFolder
  2116. //------------------------------------------------------------------------------
  2117. static ODBoolean
  2118. FindVolumeEditorsFolder( short vol, ConstStr255Param localizedFolderName, FSSpec *folderSpec )
  2119. {
  2120.     // Look for the magic invisible hint file at the root, which contains the folder name:
  2121.     OSErr err;
  2122.     short fil;
  2123.     ODBoolean targetIsFolder, wasAliased;
  2124.     
  2125.     if( FSMakeFSSpec(vol,fsRtDirID,kODEditorHintFileName, folderSpec) == noErr ) {
  2126.         short fil;
  2127.         Str63 name;
  2128.         err= FSpOpenDF(folderSpec,fsRdPerm,&fil);
  2129.         if( !err ) {
  2130.             Size size = 64;
  2131.             err= FSRead(fil,&size,name);
  2132.             if( err==eofErr && size==1L+name[0] )
  2133.                 err= noErr;
  2134.             FSClose(fil);
  2135.         }
  2136.         if( !err )
  2137.             err= FSMakeFSSpec(vol,fsRtDirID,name, folderSpec);
  2138.         if( !err )
  2139.         {
  2140.             err = ResolveAliasFile(folderSpec, kODTrue, &targetIsFolder, &wasAliased);
  2141.             if( targetIsFolder )
  2142.                 return kODTrue;
  2143.         }
  2144.     }
  2145.     
  2146.     // If there's no hint file or it lied to us, look for the current localized name:
  2147.     err = FSMakeFSSpec(vol,fsRtDirID,localizedFolderName, folderSpec);
  2148.     if( !err )
  2149.     {
  2150.         err = ResolveAliasFile(folderSpec, kODTrue, &targetIsFolder, &wasAliased);
  2151.         if( !targetIsFolder )
  2152.             return kODFalse;
  2153.     }
  2154.     
  2155.     if( err != noErr )
  2156.         return kODFalse;
  2157.     
  2158.     // We've found the folder, so create or update the hint file:
  2159.     err= HCreate(vol,fsRtDirID,kODEditorHintFileName, kODShellSignature,kODEditorHintFileType);
  2160.     if( err==noErr ) {
  2161.         // After creating file, make it invisible:
  2162.         FInfo info;
  2163.         if( HGetFInfo(vol,fsRtDirID,kODEditorHintFileName,&info) == noErr ) {
  2164.             info.fdFlags |= kIsInvisible;
  2165.             HSetFInfo(vol,fsRtDirID,kODEditorHintFileName,&info);
  2166.         }
  2167.     } else if( err!=dupFNErr ) {
  2168.         WARN("Couldn't create/update hint file, err %hd",err);
  2169.         return kODTrue;
  2170.     }
  2171.     
  2172.     // Update the file:
  2173.     err= HOpen(vol,fsRtDirID,kODEditorHintFileName, fsWrPerm, &fil);
  2174.     if( !err ) {
  2175.         long size = 1+localizedFolderName[0];
  2176.         if( !err )
  2177.             err= FSWrite(fil,&size,localizedFolderName);
  2178.         if( !err )
  2179.             err= SetEOF(fil,size);
  2180.         FSClose(fil);
  2181.         FlushVol(kODNULL,vol);
  2182.     }
  2183.     if( err )
  2184.         WARN("Err %hd writing editor hint file on vol %hd",err,vol);
  2185.     return kODTrue;
  2186. }
  2187.  
  2188.  
  2189. //------------------------------------------------------------------------------
  2190. // GetIndVolume
  2191. //------------------------------------------------------------------------------
  2192. static ODBoolean
  2193. GetIndVolume( short index, short *vRefNum )
  2194. {
  2195.     // Returns false if no more volumes.
  2196.     // Returns true but with vRefNum=0 if this volume should be skipped.
  2197.     WASSERT(index>0);
  2198.     HParamBlockRec pb;
  2199.     pb.volumeParam.ioCompletion = NULL;
  2200.     pb.volumeParam.ioNamePtr = NULL;
  2201.     pb.volumeParam.ioVolIndex = index;
  2202.     
  2203.     if( PBHGetVInfoSync(&pb) != noErr )
  2204.         return kODFalse;
  2205.  
  2206. /*    ** Disabled; enable to skip AppleShare volumes **
  2207.     
  2208.     // Determine the driver refnum of the AppleShare file system driver:
  2209.     static short afpRefNum = 0;
  2210.     if( afpRefNum==0 ) {        // Happens first time called
  2211.         if( OpenDriver("\p.AFPTranslator",&afpRefNum) != noErr )
  2212.             afpRefNum = -32768;    // some bogus value
  2213.     }
  2214.     if( pb.volumeParam.ioVDRefNum==afpRefNum )
  2215.         *vRefNum = 0;            // Volume is a server: skip it
  2216.     else
  2217. */
  2218.  
  2219.     if( pb.volumeParam.ioVDrvInfo==0 )
  2220.         *vRefNum = 0;            // Volume is offline: skip it
  2221.     else
  2222.         *vRefNum = pb.volumeParam.ioVRefNum;
  2223.     return kODTrue;
  2224. }
  2225.  
  2226.  
  2227. //------------------------------------------------------------------------------
  2228. // GetFldrDirID
  2229. //------------------------------------------------------------------------------
  2230. static ODSLong
  2231. GetFldrDirID( FSSpec theFolderSpec, ODULong *modDate /*=NULL*/ )
  2232. {
  2233.     ODSLong dirID=-1;
  2234.     CInfoPBRec    theParamBlock;
  2235.     memset (&theParamBlock,0,sizeof(theParamBlock));
  2236.     theParamBlock.dirInfo.ioFDirIndex = 0;
  2237.     theParamBlock.dirInfo.ioNamePtr = theFolderSpec.name;
  2238.     theParamBlock.dirInfo.ioVRefNum = theFolderSpec.vRefNum;
  2239.     theParamBlock.dirInfo.ioDrDirID = theFolderSpec.parID;
  2240.     ODError result = PBGetCatInfoSync((CInfoPBPtr)&theParamBlock);
  2241.     if (result == noErr && (theParamBlock.hFileInfo.ioFlAttrib & (1<<4)) ) {
  2242.         dirID = theParamBlock.dirInfo.ioDrDirID;
  2243.         if( modDate )
  2244.             *modDate = theParamBlock.dirInfo.ioDrMdDat;
  2245.     }
  2246.  
  2247.     return dirID;
  2248. }
  2249.  
  2250.  
  2251. //------------------------------------------------------------------------------
  2252. // GetDirModDateAndParent
  2253. //------------------------------------------------------------------------------
  2254. static void
  2255. GetDirModDateAndParent( short vol, long dir, ODULong *modDate, long *parent )
  2256. {
  2257.     CInfoPBRec    pb;
  2258.     memset (&pb,0,sizeof(pb));
  2259.     pb.dirInfo.ioFDirIndex = -1;
  2260.     pb.dirInfo.ioNamePtr = kODNULL;
  2261.     pb.dirInfo.ioVRefNum = vol;
  2262.     pb.dirInfo.ioDrDirID = dir;
  2263.     ODError result = PBGetCatInfoSync((CInfoPBPtr)&pb);
  2264.     if( result )
  2265.         *modDate = *parent = 0;
  2266.     else {
  2267.         *modDate = pb.dirInfo.ioDrMdDat;
  2268.         *parent = pb.dirInfo.ioDrParID;
  2269.     }
  2270. }
  2271.  
  2272.  
  2273. //------------------------------------------------------------------------------
  2274. // ExtractIText
  2275. //------------------------------------------------------------------------------
  2276. static ODSize ExtractIText(ODSize bufferPos, ODSession* session, 
  2277.                                            ODValueNameSpace *theNameSpace, ODISOStr key)
  2278. {
  2279.     ODTradITextData* theODName = kODNULL;
  2280.     Environment*     ev = somGetGlobalEnvironment ();
  2281.  
  2282.     ScriptCode theScriptCode = *(ScriptCode*)bufferPos;
  2283.     bufferPos += sizeof(ScriptCode);
  2284.     
  2285.     LangCode theLangCode = *(LangCode*)bufferPos;
  2286.     bufferPos += sizeof(LangCode);
  2287.     
  2288.     ODUShort theODNameLen = *(ODUShort*)bufferPos;
  2289.     bufferPos += sizeof(ODUShort);
  2290.     
  2291.     char* theText = (char*)ODNewPtrClear(theODNameLen+1, kDefaultHeapID);
  2292.     ODBlockMove((ODPtr)bufferPos, (ODPtr)theText, theODNameLen);
  2293.     //theODName = CreateIText(theScriptCode, theLangCode, theText );
  2294.  
  2295.     theODName = CreateFlatIText(theScriptCode, theLangCode, theText, theODNameLen);
  2296.     ODDisposePtr( theText );
  2297.  
  2298.     bufferPos += theODNameLen;
  2299.     
  2300.     TRY
  2301.         if (theNameSpace->GetType(ev) != kODNSDataTypeODValue)
  2302.             THROW(kODErrInvalidNSType);
  2303.         // no need to remove a previously registered key
  2304.  
  2305.             // Register the new entry with theNameSpace 
  2306.         ValueNameSpaceRegister(theNameSpace, ev, key, 
  2307.                 (ODPtr)theODName,theODNameLen+sizeof(ODTradITextDataHeader));
  2308.     CATCH_ALL
  2309.     ENDTRY
  2310.     
  2311.     ODDisposePtr( theODName );
  2312.  
  2313.     return (ODSize)bufferPos;
  2314. }
  2315.  
  2316. //------------------------------------------------------------------------------
  2317. // ExtractISOStringList
  2318. //------------------------------------------------------------------------------
  2319. static ODSize ExtractISOStringList(ODSize bufferPos, ODSession* session, 
  2320.                                            ODObjectNameSpace *theNameSpace, ODISOStr key)
  2321. {
  2322.     ODTypeList*        valueList = kODNULL;
  2323.     ODUShort        valueItemLen;
  2324.     ODISOStr        valueItem = kODNULL;
  2325.     ODObject*        entry = kODNULL;
  2326.     Environment*     ev = somGetGlobalEnvironment ();
  2327.  
  2328.     ODUShort    valueCount = *(ODUShort*)bufferPos;
  2329.     bufferPos += sizeof(ODUShort);
  2330.     
  2331.     valueList = session->GetStorageSystem(ev)->CreateTypeList(ev,(ODTypeList*)kODNULL);
  2332.  
  2333.     for(ODUShort j=1; j<= valueCount; j++)
  2334.     {
  2335.         valueItemLen = *(ODUShort*)bufferPos;
  2336.         bufferPos += sizeof(ODUShort);
  2337.  
  2338.         valueItem = (ODISOStr)ODNewPtrClear((ODSize)valueItemLen+1, kDefaultHeapID);
  2339.         ODBlockMove((ODPtr)bufferPos, (ODPtr)valueItem, valueItemLen);
  2340.         bufferPos += valueItemLen;
  2341.         
  2342.         valueList->AddLast( ev, (ODType)valueItem );
  2343.         ODDisposePtr((ODPtr)valueItem);
  2344.     }
  2345.     
  2346.         // Register entry with theNameSpace
  2347.     TRY
  2348.         if (theNameSpace->GetType(ev) != kODNSDataTypeODObject)
  2349.             THROW(kODErrInvalidNSType);
  2350.         
  2351.         // no need to remove a previously registered key
  2352.  
  2353.             // Register the new entry with theNameSpace 
  2354.         theNameSpace->Register( ev, key, (ODObject*)valueList );
  2355.     CATCH_ALL
  2356.         ODDeleteObject( valueList );
  2357.     ENDTRY
  2358.     
  2359.     return (ODSize)bufferPos;
  2360. }
  2361.  
  2362. //------------------------------------------------------------------------------
  2363. // ExtractOSType
  2364. //------------------------------------------------------------------------------
  2365. static ODSize ExtractOSType(ODSize bufferPos, ODSession* session, 
  2366.                                            ODValueNameSpace *theNameSpace, ODISOStr key)
  2367. {
  2368.     Environment*     ev = somGetGlobalEnvironment ();
  2369.  
  2370.     ODOSType    theODType = *(ODOSType*)bufferPos;
  2371.     bufferPos += sizeof(ODOSType);
  2372.     
  2373.         // Register entry with theNameSpace
  2374.     TRY
  2375.         if (theNameSpace->GetType(ev) != kODNSDataTypeODValue)
  2376.             THROW(kODErrInvalidNSType);
  2377.         // no need to remove a previously registered key
  2378.  
  2379.             // Register the new entry with theNameSpace 
  2380.         ValueNameSpaceRegister(theNameSpace,ev,key,&theODType, 
  2381.                                                           sizeof(ODOSType));
  2382.     CATCH_ALL
  2383.     ENDTRY
  2384.     
  2385.     return (ODSize)bufferPos;
  2386. }
  2387.  
  2388. //------------------------------------------------------------------------------
  2389. // ExtractPltfrmTypeSpac
  2390. //------------------------------------------------------------------------------
  2391. static ODSize ExtractPltfrmTypeSpac(ODSize bufferPos, ODSession* session, 
  2392.                                            ODISOStr key)
  2393. {
  2394.     ODObjectNameSpace*         edKindsNmSpc = kODNULL;
  2395.     ODObjectNameSpace*         kindCategoryNS = kODNULL;
  2396.     ODPlatformType            thePlfType;
  2397.     ODPlatformTypeSpace        thePlfTypeSpc;
  2398.     ODUShort                theCategoryLen;
  2399.     ODType                    theKind;
  2400.     ODISOStr                theCategory = kODNULL;
  2401.     ODObject*                entry = kODNULL;
  2402.     ODTypeList*                valueList = kODNULL;
  2403.     Environment*             ev = somGetGlobalEnvironment ();
  2404.  
  2405.     ODUShort valueCount = *(ODUShort*)bufferPos;
  2406.     bufferPos += sizeof(ODUShort);
  2407.     
  2408.     for(ODUShort j=1; j<= valueCount; j++)
  2409.     {
  2410.             // First read thePlfTypeSpc
  2411.         thePlfTypeSpc = *(ODPlatformTypeSpace*)bufferPos;
  2412.         bufferPos += sizeof(ODPlatformTypeSpace);
  2413.         
  2414.             // Next read thePlfType
  2415.         thePlfType = *(ODPlatformType*)bufferPos;
  2416.         bufferPos += sizeof(ODPlatformType);
  2417.         
  2418.         ODTranslation* translation = session->GetTranslation(ev);
  2419.         theKind = translation->GetISOTypeFromPlatformType(ev, thePlfType, thePlfTypeSpc);
  2420.         
  2421.             // Register entry with theNameSpace
  2422.         edKindsNmSpc = (ODObjectNameSpace*)(session->GetNameSpaceManager(ev)->
  2423.                                             HasNameSpace(ev, kODEditorKinds));
  2424.         TRY
  2425.             if (edKindsNmSpc->GetType(ev) != kODNSDataTypeODObject)
  2426.                 THROW(kODErrInvalidNSType);
  2427.                 
  2428.                 // if there is already a list registered add to end of it
  2429.             if (edKindsNmSpc->GetEntry(ev,key, (ODObject**)&valueList ))
  2430.                 valueList->AddLast( ev, theKind );
  2431.             else
  2432.             {    // else make a new list
  2433.                 valueList = session->GetStorageSystem(ev)->
  2434.                             CreateTypeList(ev, (ODTypeList*)kODNULL);
  2435.                 valueList->AddLast( ev, theKind );
  2436.  
  2437.                     // Register the new entry with edKindsNmSpc 
  2438.                 edKindsNmSpc->Register( ev, key, (ODObject*)valueList );
  2439.             }
  2440.         
  2441.             ODValueNameSpace *userStringNS = (ODValueNameSpace*)
  2442.                     (session->GetNameSpaceManager(ev)->HasNameSpace(ev, kODKindUserString));
  2443.             bufferPos = ExtractIText(bufferPos, session, userStringNS, theKind);
  2444.             
  2445.             kindCategoryNS = (ODObjectNameSpace*)(session->GetNameSpaceManager(ev)->
  2446.                                                 HasNameSpace(ev, kODKind));
  2447.         
  2448.             theCategoryLen = *(ODUShort*)bufferPos;
  2449.             bufferPos += sizeof(ODUShort);
  2450.         
  2451.             theCategory = (ODISOStr)ODNewPtrClear((ODSize)theCategoryLen+1, kDefaultHeapID);
  2452.             ODBlockMove((ODPtr)bufferPos, (ODPtr)theCategory, theCategoryLen);
  2453.             bufferPos += theCategoryLen;
  2454.         
  2455.             TRY
  2456.                 if (kindCategoryNS->GetType(ev) != kODNSDataTypeODObject)
  2457.                     THROW(kODErrInvalidNSType);
  2458.                 // if there is already a list registered add to end of it
  2459.                 if (kindCategoryNS->GetEntry(ev,theKind, (ODObject**)&valueList ))
  2460.                     valueList->AddLast( ev, theCategory );
  2461.                 else
  2462.                 {    // else make a new list
  2463.                     valueList = session->GetStorageSystem(ev)->
  2464.                                          CreateTypeList(ev, (ODTypeList*)kODNULL);
  2465.                     valueList->AddLast( ev, theCategory );
  2466.                         // Register the new entry with kindCategoryNS 
  2467.                     kindCategoryNS->Register( ev, theKind, (ODObject*)valueList );
  2468.                 }
  2469.             CATCH_ALL
  2470.             ENDTRY
  2471.  
  2472.             ODDisposePtr( theCategory );
  2473.             
  2474.         CATCH_ALL
  2475.         ENDTRY
  2476.  
  2477.         ODDisposePtr( theKind );
  2478.     }    
  2479.     
  2480.     return (ODSize)bufferPos;
  2481. }
  2482.  
  2483. //------------------------------------------------------------------------------
  2484. // ExtractISOString
  2485. //------------------------------------------------------------------------------
  2486. static ODSize ExtractISOString(ODSize bufferPos, ODSession* session, 
  2487.                                            ODValueNameSpace *theNameSpace, ODISOStr key)
  2488. {
  2489.     ODISOStr            valueItem = kODNULL;
  2490.     Environment*         ev = somGetGlobalEnvironment ();
  2491.  
  2492.     ODUShort    valueItemLen = *(ODUShort*)bufferPos;
  2493.     bufferPos += sizeof(ODUShort);
  2494.  
  2495.     valueItem = (ODISOStr)ODNewPtrClear((ODSize)valueItemLen+1, kDefaultHeapID);
  2496.     ODBlockMove((ODPtr)bufferPos, (ODPtr)valueItem, valueItemLen);
  2497.     bufferPos += valueItemLen;
  2498.  
  2499.         // Register entry with theNameSpace
  2500.     TRY
  2501.         if (theNameSpace->GetType(ev) != kODNSDataTypeODValue)
  2502.             THROW(kODErrInvalidNSType);
  2503.  
  2504.         ODNameSpaceManager *theNmSpcMgr = theNameSpace->GetNameSpaceManager(ev);
  2505.         // no need to remove a previously registered key
  2506.  
  2507.             // Register the new entry with theNameSpace 
  2508.         ValueNameSpaceRegister( theNameSpace, ev, key, (ODPtr)valueItem, 
  2509.                                                            valueItemLen+1 );
  2510.     CATCH_ALL
  2511.     ENDTRY
  2512.     
  2513.     ODDisposePtr( (ODPtr)valueItem );
  2514.     
  2515.     return (ODSize)bufferPos;
  2516. }
  2517.  
  2518. //------------------------------------------------------------------------------
  2519. // ExtractHelpFileName
  2520. //------------------------------------------------------------------------------
  2521. static ODSize ExtractHelpFileName(    ODSize bufferPos, 
  2522.                                     ODSession* session, 
  2523.                                     const ODFileSpec* libspec,
  2524.                                     ODValueNameSpace *theNameSpace, 
  2525.                                     ODISOStr editorID)
  2526. {
  2527.     Environment*     ev = somGetGlobalEnvironment ();
  2528.     ODFileSpec         fsspec;
  2529.  
  2530.         // Register entry with theNameSpace
  2531.     TRY
  2532.  
  2533.         fsspec.vRefNum = libspec->vRefNum;
  2534.         fsspec.parID = libspec->parID;
  2535.     
  2536.         ODUShort fileNameLen = *(ODUShort*)bufferPos;
  2537.         bufferPos += sizeof(ODUShort);
  2538.         fsspec.name[0] = fileNameLen;
  2539.         
  2540.         ODBlockMove((ODPtr)bufferPos, (ODPtr)&fsspec.name[1], fileNameLen);
  2541.         bufferPos += fileNameLen;
  2542.     
  2543.         if (theNameSpace->GetType(ev) != kODNSDataTypeODValue)
  2544.             THROW(kODErrInvalidNSType);
  2545.     
  2546.             // Register the new entry with theNameSpace 
  2547.         ValueNameSpaceRegister( theNameSpace, ev, editorID, 
  2548.                                                 (ODPtr)&fsspec, sizeof(fsspec));
  2549.     CATCH_ALL
  2550.     ENDTRY
  2551.         
  2552.     return (ODSize)bufferPos;
  2553. }
  2554.  
  2555. //------------------------------------------------------------------------------
  2556. // Cache_nmap
  2557. //------------------------------------------------------------------------------
  2558. static void
  2559. Cache_nmap( PlatformFile* cacheFile, ODSize bufferSize, Handle mappingPair,
  2560.             const FSSpec *fsspec )
  2561. {
  2562.     ODSLong    sizeofsize = sizeof( ODSize );
  2563.     ODSLong    sizeoflong = sizeof( long );
  2564.     ODSize    sizeofname = (ODSize)fsspec->name[0];
  2565.  
  2566.     if (cacheFile)
  2567.     {
  2568.         cacheFile->Write( (ODSByte*) &fsspec->parID, &sizeoflong );
  2569.         cacheFile->Write( (ODSByte*) &sizeofname, &sizeofsize );
  2570.         cacheFile->Write( (ODSByte*) &fsspec->name[1], (ODSLong*)&sizeofname );
  2571.         cacheFile->Write( (ODSByte*) &bufferSize, &sizeofsize );
  2572.         cacheFile->Write( (ODSByte*) *mappingPair, (ODSLong*)&bufferSize );
  2573.     }
  2574. }
  2575.  
  2576. //------------------------------------------------------------------------------
  2577. // MoveToTrash
  2578. //------------------------------------------------------------------------------
  2579. static void
  2580. MoveToTrash( short vRefnum, long dirID, Str255 name )
  2581. {
  2582.     short foundVRefNum;
  2583.     long  foundDirID;
  2584.     
  2585.     if(!FindFolder(vRefnum, kTrashFolderType, kDontCreateFolder, 
  2586.                                 &foundVRefNum, &foundDirID))
  2587.     {
  2588.  
  2589.         CMovePBRec paramBlock ;
  2590.         memset( ¶mBlock, 0, sizeof(paramBlock) );
  2591.         
  2592.         paramBlock.ioNamePtr = name ;
  2593.         paramBlock.ioVRefNum = foundVRefNum ;
  2594.         paramBlock.ioNewDirID = foundDirID ;
  2595.         paramBlock.ioDirID = dirID ;
  2596.         
  2597.         (void) HDelete(foundVRefNum,foundDirID,name);     // ignore error (may not exist)
  2598.         OSErr result = PBCatMoveSync( ¶mBlock );
  2599.         if (result)
  2600.             (void) HDelete(vRefnum,dirID,name); 
  2601.     }
  2602.     else
  2603.         (void) HDelete(vRefnum,dirID,name); 
  2604. }
  2605.  
  2606.  
  2607. //------------------------------------------------------------------------------
  2608. // Read_aete_Resources
  2609. //------------------------------------------------------------------------------
  2610. static void
  2611. Read_aete_Resources( FSSpec* fsspec, AEDescList* aetes )
  2612. {
  2613.     LOG("* Reading 'aete's from file '%P' in (%hd,%ld)\n",fsspec->name,
  2614.             fsspec->vRefNum,fsspec->parID);
  2615.     TRY
  2616.         ODSShort aeteCount = Count1Resources( typeAETE );
  2617.         for (short i=1; i<=aeteCount; i++) 
  2618.         {
  2619.                 // Get the Resource
  2620.             Handle aete = Get1IndResource(typeAETE, i);
  2621.             ODError result = ResError();
  2622.             
  2623.             if ( aete != nil && !result )
  2624.             {
  2625.                 ODLockHandle((ODHandle) aete);
  2626.                 
  2627.                 ODSize bufferSize = ODGetHandleSize((ODHandle)aete);
  2628.                 THROW_IF_ERROR( AEPutPtr(aetes, 0, typeAETE, *aete, bufferSize) );
  2629.                 
  2630.                 ReleaseResource( aete );
  2631.             }
  2632.         }
  2633.     CATCH_ALL
  2634.         WARN("Error %ld reading aetes for file %#s",ErrorCode(),fsspec->name);
  2635.     ENDTRY
  2636. }
  2637.  
  2638. #if PRAGMA_ALIGN_SUPPORTED
  2639. #pragma options align=mac68k
  2640. #endif
  2641.  
  2642. struct partialAETE {
  2643.     short    version;
  2644.     short    language;
  2645.     short    script;
  2646. };
  2647.  
  2648. #if PRAGMA_ALIGN_SUPPORTED
  2649. #pragma options align=reset
  2650. #endif
  2651.  
  2652. //------------------------------------------------------------------------------
  2653. // AddAETEs
  2654. //------------------------------------------------------------------------------
  2655. static void
  2656. AddAETEs(PlatformFile* cacheFile, ODSLong languageCode, AEDescList* aeteList)
  2657. {
  2658.     ODPtr        ptr;
  2659.     ODULong        size;
  2660.     ODSLong        i, n, lang;
  2661.     AEDesc        temp;
  2662.     AEDesc        list;
  2663.     DescType    type;
  2664.     
  2665.     ptr = cacheFile->ReadResourcePtr(typeAECache, 0, &size);
  2666.     if (ptr != kODNULL)
  2667.     {
  2668.         PtrToHand(ptr, &temp.dataHandle, size);
  2669.         ODDisposePtr(ptr);
  2670.         temp.descriptorType = typeAERecord;
  2671.         THROW_IF_ERROR( AEGetKeyDesc(&temp, keyDirectObject, typeAEList, &list) );
  2672.         ODDisposeHandle(temp.dataHandle);
  2673.         temp.dataHandle = kODNULL;
  2674.         THROW_IF_ERROR( AECountItems(&list, &n) );
  2675.         for (i = 1; i <= n; i++)
  2676.         {
  2677.             THROW_IF_ERROR( AEGetNthDesc(&list, i, typeAETE, &type, &temp) );
  2678.             lang = (((**(partialAETE**)temp.dataHandle).script & 0xFF) << 8) | 
  2679.                     ((**(partialAETE**)temp.dataHandle).language & 0xFF);
  2680.             if (lang == languageCode)
  2681.                 THROW_IF_ERROR( AEPutDesc(aeteList, 0, &temp) );
  2682.             THROW_IF_ERROR( AEDisposeDesc(&temp) );
  2683.         }
  2684.         THROW_IF_ERROR( AEDisposeDesc(&list) );
  2685.     }
  2686. }
  2687.  
  2688.  
  2689. //------------------------------------------------------------------------------
  2690. // GetODPrefsFolder
  2691. //------------------------------------------------------------------------------
  2692.  
  2693. static ODBoolean GetODPrefsFolder(ODSShort* prefVol, ODSLong* prefDir )
  2694. {
  2695.     Str255            prefFolderName;
  2696.     ODULong         prefModDate;
  2697.     OSErr            result;
  2698.     ODSLong            tempDir;
  2699.  
  2700.         //find preferences folder
  2701.     ODGetString(prefFolderName,kODPrefsFolderNameStrID);
  2702.  
  2703.     TRY{
  2704.         FindMagicFolder(kPreferencesFolderType,prefFolderName,
  2705.                             prefVol, prefDir, &prefModDate);
  2706.     }CATCH_ALL{
  2707.         result =  FindFolder(kOnSystemDisk, kPreferencesFolderType, 
  2708.                         kDontCreateFolder, prefVol, &tempDir);
  2709.         result = DirCreate(*prefVol, tempDir, prefFolderName, prefDir);
  2710.         if (result != noErr)
  2711.             return kODFalse;
  2712.     }ENDTRY
  2713.     
  2714.     return kODTrue;
  2715. }
  2716.  
  2717. //------------------------------------------------------------------------------
  2718. // ConstructCacheFileName
  2719. //------------------------------------------------------------------------------
  2720.  
  2721. static OSErr ConstructCacheFileName(ODSShort fldrVRefNum, ODSLong fldrDirID, 
  2722.                                         ODULong fldrModDate, Str255* fileName )
  2723. {
  2724.     OSErr theError = noErr;
  2725.     ParamBlockRec pb;
  2726.     
  2727.     pb.volumeParam.ioNamePtr = (StringPtr)fileName;
  2728.     pb.volumeParam.ioVRefNum = fldrVRefNum;
  2729.     pb.volumeParam.ioVolIndex = 0;             /* Use vRefNum */
  2730.     theError = PBGetVInfoSync(&pb);
  2731.     if (theError == noErr)
  2732.     {
  2733.         Str255        dateString;
  2734.         IUDateString(fldrModDate, shortDate, dateString);
  2735.  
  2736.         ConcatPascalStrings( *fileName, "\p " );
  2737.         ConcatPascalStrings( *fileName, (ConstStr255Param)dateString );
  2738.     }
  2739.     return theError;
  2740. }
  2741.  
  2742. //------------------------------------------------------------------------------
  2743. // DeleteOldCacheFiles
  2744. //------------------------------------------------------------------------------
  2745.  
  2746. static void DeleteOldCacheFiles()
  2747. {
  2748.     ODSShort        prefVol;
  2749.     ODSLong            prefDir;
  2750.  
  2751.     if (GetODPrefsFolder( &prefVol, &prefDir ))
  2752.     {
  2753.         CInfoPBRec    pb;
  2754.         Str255 fileName;
  2755.         Str255 prefFileName;
  2756.         ODGetString(prefFileName,kODPrefsFileNameStrID);
  2757.  
  2758.             // Loop through all the files in folder
  2759.         memset (&pb,0,sizeof(pb));
  2760.         for( pb.hFileInfo.ioFDirIndex = 1; kODTrue; pb.hFileInfo.ioFDirIndex++ )
  2761.         {
  2762.                 //need to do this each time since PBGetCatInfo call returns val here
  2763.             pb.hFileInfo.ioNamePtr = (StringPtr)&fileName;
  2764.             pb.hFileInfo.ioVRefNum = prefVol;
  2765.             pb.hFileInfo.ioDirID = prefDir;  
  2766.             
  2767.             if( PBGetCatInfoSync( &pb ) != noErr )
  2768.                 break;
  2769.             
  2770.             if ( !(pb.dirInfo.ioFlAttrib & (1<<4)) && 
  2771.                 !(pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias) &&
  2772.                 (pb.hFileInfo.ioFlFndrInfo.fdCreator == kODShellSignature) )
  2773.             {
  2774.                 if (!EqualPascalStrings(fileName, prefFileName))
  2775.                 {
  2776.                     ODULong        secs;
  2777.                     GetDateTime(&secs);
  2778.                         // if this cache file is over 30 days old, delete it
  2779.                     Str255        dateString;
  2780.                     ODULong aMonthAgo = secs - (30*24*60*60);
  2781.                     IUDateString(aMonthAgo, shortDate, dateString);
  2782.                     if (pb.hFileInfo.ioFlMdDat < aMonthAgo )
  2783.                     {
  2784.                         MoveToTrash( pb.hFileInfo.ioVRefNum, 
  2785.                                      pb.hFileInfo.ioFlParID, fileName );
  2786.                     }
  2787.                 }
  2788.             }
  2789.         }
  2790.     }
  2791. }
  2792.  
  2793.  
  2794. //------------------------------------------------------------------------------
  2795. // LoadableLibrary
  2796. //------------------------------------------------------------------------------
  2797.  
  2798. static ODBoolean LoadableLibrary(ODSShort resRefNum)
  2799. {
  2800.     ODBoolean    libIsLoadable = kODFalse;
  2801.     
  2802.  
  2803.     ODHandle cfrg = (ODHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
  2804.     ODError result = ResError();
  2805.  
  2806.     if (cfrg) {
  2807.         DetachResource(cfrg);
  2808.         result = ResError();
  2809.     } else
  2810.         if( result==noErr ) result=resNotFound;
  2811.  
  2812.     if (result == noErr)
  2813.     {
  2814.         ODLockHandle( cfrg);
  2815.         
  2816.         ODSize bufferPos = (ODSize)*cfrg;
  2817.         cfragHeader theHeader;
  2818.         cfragDescriptor theDesc;
  2819.         
  2820.         ODBlockMove((ODPtr)bufferPos, (ODPtr)&theHeader, sizeof(cfragHeader));
  2821.         bufferPos += sizeof(cfragHeader);
  2822.         
  2823.         for(ODUShort i=0; i< theHeader.numFragDescs; i++)
  2824.         {
  2825.             ODBlockMove((ODPtr)bufferPos, (ODPtr)&theDesc.header, sizeof(cfragDescHeader));
  2826.             bufferPos += sizeof(cfragDescHeader);
  2827.             
  2828.             ODULong nameLen = theDesc.header.infoRecLen - sizeof(cfragDescHeader);
  2829.             ODBlockMove((ODPtr)bufferPos, (ODPtr)&theDesc.fragName, nameLen);
  2830.             bufferPos += nameLen;
  2831.             
  2832.             if (theDesc.header.arch == kCurrentCFragArch)
  2833.             {
  2834.                 libIsLoadable = kODTrue;
  2835.                 break;
  2836.             }
  2837.         }
  2838.  
  2839.         ODDisposeHandle( cfrg );
  2840.     }
  2841.     
  2842.     return libIsLoadable;
  2843. }
  2844.  
  2845. //------------------------------------------------------------------------------
  2846. // ResolveLocalAliasFile
  2847. //------------------------------------------------------------------------------
  2848.  
  2849. // This is a replacement of ResolveAliasFile that does not try to mount the servers
  2850.  
  2851. static OSErr ResolveLocalAliasFile(FSSpec *theSpec, Boolean resolveAliasChains, 
  2852.                                     Boolean *targetIsFolder, Boolean *wasAliased)
  2853. {
  2854.     OSErr             err;
  2855.     CInfoPBRec        pb;
  2856.  
  2857.     *targetIsFolder = kODFalse;
  2858.     memset (&pb,0,sizeof(pb));
  2859.     do {
  2860.         short aliasCount = 0;
  2861.         err = -1; // should be file not found
  2862.         *wasAliased = kODFalse;
  2863.         short aliasFile = FSpOpenResFile(theSpec,fsRdPerm);
  2864.         if (aliasFile != -1) {
  2865.             ODHandle aliasHandle = kODNULL;
  2866.             aliasHandle = Get1Resource(rAliasType, 0);
  2867.             if (aliasHandle) {
  2868.                 aliasCount = 1;
  2869.                 ODBoolean needsUpdate = kODFalse;
  2870.                 err = MatchAlias(theSpec, kARMNoUI+kARMSearch, (AliasHandle)aliasHandle, &aliasCount, (FSSpecArrayPtr)theSpec, &needsUpdate, kODNULL, kODNULL);
  2871.             }
  2872.             CloseResFile( aliasFile );
  2873.         }
  2874.         if (err == noErr) {
  2875.             if (aliasCount == 1) {
  2876.                 pb.hFileInfo.ioNamePtr = (StringPtr)&theSpec->name;
  2877.                 pb.hFileInfo.ioVRefNum = theSpec->vRefNum;
  2878.                 pb.hFileInfo.ioDirID = theSpec->parID;  
  2879.                 
  2880.                 if( PBGetCatInfoSync( &pb ) == noErr ) {
  2881.                     if ( (pb.dirInfo.ioFlAttrib & (1<<4)) ) {
  2882.                         // if this is a folder, we are done
  2883.                         *targetIsFolder = kODTrue;    
  2884.                     }
  2885.                     else
  2886.                         *wasAliased = (pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias) ? kODTrue : kODFalse;
  2887.                 }
  2888.             }
  2889.             else
  2890.                 err = -1; // should be file not found
  2891.         }
  2892.     } while (*wasAliased & resolveAliasChains);
  2893.     return err;
  2894. }
  2895.  
  2896.  
  2897. //eof
  2898.